From 22c69f3f088dd9bc5d0c42851116b39bb0a0f2ad Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Wed, 1 Nov 2023 21:31:31 +0100 Subject: [PATCH 01/77] Changed to block processing and added IHeaders --- .../rat/analysis/HeaderCheckWorker.java | 95 +++++++++---------- .../apache/rat/analysis/IHeaderMatcher.java | 52 +--------- .../org/apache/rat/analysis/IHeaders.java | 34 +++++++ .../rat/analysis/LicenseCollection.java | 46 +-------- .../apache/rat/analysis/UnknownLicense.java | 16 +--- .../matchers/AbstractMatcherContainer.java | 6 -- .../matchers/AbstractSimpleMatcher.java | 38 +------- .../rat/analysis/matchers/AndMatcher.java | 30 ++---- .../analysis/matchers/CopyrightMatcher.java | 11 ++- .../analysis/matchers/FullTextMatcher.java | 56 +---------- .../rat/analysis/matchers/NotMatcher.java | 25 +---- .../rat/analysis/matchers/OrMatcher.java | 49 ++-------- .../analysis/matchers/SPDXMatcherFactory.java | 5 +- .../analysis/matchers/SimpleRegexMatcher.java | 6 +- .../analysis/matchers/SimpleTextMatcher.java | 5 +- .../builders/MatcherRefBuilder.java | 17 +--- .../apache/rat/license/LicenseSetFactory.java | 16 +--- .../org/apache/rat/license/SimpleLicense.java | 15 +-- .../rat/analysis/AnalyserFactoryTest.java | 9 +- .../rat/analysis/HeaderCheckWorkerTest.java | 2 - .../analysis/license/AbstractLicenseTest.java | 12 +-- .../analysis/license/DirectoryScanner.java | 15 +-- .../matchers/AbstractMatcherTest.java | 65 +++++++++++++ .../rat/analysis/matchers/AndMatcherTest.java | 48 ++-------- .../matchers/CopyrightMatcherTest.java | 15 ++- .../matchers/FullTextMatcherTest.java | 45 ++------- .../rat/analysis/matchers/NotMatcherTest.java | 35 +------ .../rat/analysis/matchers/OrMatcherTest.java | 47 +-------- .../analysis/matchers/SPDXMatcherTest.java | 48 +--------- .../matchers/SimpleCopyrightTests.java | 13 +-- .../matchers/SimpleRegexMatcherTest.java | 40 +------- .../matchers/SimpleTextMatcherTest.java | 50 +--------- .../rat/report/xml/XmlReportFactoryTest.java | 3 +- .../apache/rat/report/xml/XmlReportTest.java | 1 + .../rat/testhelpers/TestingLicense.java | 15 +-- .../rat/testhelpers/TestingMatcher.java | 27 +----- .../src/test/java/org/example/Matcher.java | 3 +- .../test/resources/antunit/report-junit.xml | 3 +- .../antunit/report-normal-operation.xml | 3 +- 39 files changed, 268 insertions(+), 753 deletions(-) create mode 100644 apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaders.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AbstractMatcherTest.java 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 01ef13b71..934886c54 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,9 +21,12 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; +import java.util.Locale; import java.util.Objects; +import org.apache.commons.io.IOUtils; import org.apache.rat.ConfigurationException; +import org.apache.rat.analysis.matchers.FullTextMatcher; import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; import org.apache.rat.license.ILicense; @@ -34,7 +37,7 @@ * Note that this class is not thread safe. *

*/ -class HeaderCheckWorker { +public class HeaderCheckWorker { /* TODO revisit this class. It is only used in one place and can be moved inline as the DocumentHeaderAnalyser states. * However, it may also be possible to make the entire set threadsafe so that multiple files can be checked simultaneously. @@ -50,9 +53,40 @@ class HeaderCheckWorker { private final ILicense license; private final Document document; - private int headerLinesToRead; - private boolean finished = false; + /** + * Read the input and perform the header check. + * + * @throws RatHeaderAnalysisException on IO Exception. + * @throws IOException + */ + public static IHeaders readHeader(BufferedReader reader, int numberOfLines) throws IOException { + final StringBuilder headers = new StringBuilder(); + int headerLinesRead=0; + String line; + + while (headerLinesRead < numberOfLines && (line = reader.readLine()) != null) { + headers.append(line).append("\n"); + } + final String raw = headers.toString(); + final String pruned = FullTextMatcher.prune(raw).toLowerCase(Locale.ENGLISH); + return new IHeaders() { + @Override + public String raw() { + return raw; + } + + @Override + public String pruned() { + return pruned; + } + + public String toString() { + return "HeaderCheckWorker"; + } + }; + } + /** * Convenience constructor wraps given Reader in a * BufferedReader. @@ -87,58 +121,23 @@ public HeaderCheckWorker(Reader reader, int numberOfRetainedHeaderLine, final IL this.document = name; } - /** - * @return {@code true} if the header check is complete. - */ - public boolean isFinished() { - return finished; - } - /** * Read the input and perform the header check. * * @throws RatHeaderAnalysisException on IO Exception. */ public void read() throws RatHeaderAnalysisException { - if (!finished) { - final StringBuilder headers = new StringBuilder(); - headerLinesToRead = numberOfRetainedHeaderLines; - try { - while (readLine(headers)) { - // do nothing - } - if (license.finalizeState().asBoolean()) { - document.getMetaData().reportOnLicense(license); - } else { - document.getMetaData().reportOnLicense(UnknownLicense.INSTANCE); - document.getMetaData().set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, headers.toString())); - } - } catch (IOException e) { - throw new RatHeaderAnalysisException("Cannot read header for " + document, e); - } - license.reset(); - } - finished = true; - } - - boolean readLine(StringBuilder headers) throws IOException { - String line = reader.readLine(); - boolean result = line != null; - if (result) { - if (headerLinesToRead-- > 0) { - headers.append(line); - headers.append('\n'); - } - switch (license.matches(line)) { - case t: - result = false; - break; - case f: - case i: - result = true; - break; + try { + final IHeaders headers = readHeader(reader, numberOfRetainedHeaderLines); + if (license.matches(headers)) { + document.getMetaData().reportOnLicense(license); + } else { + document.getMetaData().reportOnLicense(UnknownLicense.INSTANCE); + document.getMetaData().set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, headers.raw())); } + } catch (IOException e) { + throw new RatHeaderAnalysisException("Cannot read header for " + document, e); } - return result; + license.reset(); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java index a4aacf8f6..3724951d7 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java @@ -32,40 +32,6 @@ * For implementations that need to check multiple lines the implementation must cache the earlier lines. */ public interface IHeaderMatcher { - /** - * The state of the matcher. - * - */ - enum State { - t("true"), f("false"), i("indeterminent"); - - private final String desc; - - State(String desc) { - this.desc = desc; - } - - public boolean asBoolean() { - switch (this) { - case t : return true; - case f : return false; - default: - case i : throw new IllegalStateException( "'asBoolean' should never be called on an indeterminate state"); - } - } - - @Override - public String toString() { - return super.toString()+" "+desc; - } - } - /** * Get the identifier for this matcher. *

All matchers must have unique identifiers

@@ -84,24 +50,10 @@ public String toString() { * Attempts to match {@code line} and returns the State after * the match is attempted. * - * @param line next line of text, not null + * @param headers the representations of the headers to check * @return the new state after the matching was attempted. */ - State matches(String line); - - /** - * Gets the final state for this matcher. This is called after the EOF on the - * input. At this point there should be no matchers in an {@code State.i} state. - */ - State finalizeState(); - - /** - * Gets the the current state of the matcher. All matchers should be - * in {@code State.i} at the start. - * - * @return the current state of the matcher. - */ - State currentState(); + boolean matches(IHeaders headers); /** * An IHeaderMatcher builder. diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaders.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaders.java new file mode 100644 index 000000000..fc45275b5 --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaders.java @@ -0,0 +1,34 @@ +package org.apache.rat.analysis; +/* + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + */ + +/** + * The processed headers from a file. + */ +public interface IHeaders { + /** + * @return the raw header as read from the file. + */ + public String raw(); + /** + * @return The pruned header. + */ + public String pruned(); + +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java index 57ee9de3d..1b674fad0 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java @@ -38,7 +38,6 @@ class LicenseCollection extends AbstractMatcherContainer implements ILicense { .setLicenseFamilyName("HeaderMatcherCollection default license family").build(); private final Collection enclosed; private ILicense matchingLicense; - private State lastState; /** * Constructs the LicenseCollection from the provided ILicense collection. @@ -48,7 +47,6 @@ public LicenseCollection(Collection enclosed) { super(enclosed); this.enclosed = Collections.unmodifiableCollection(enclosed); this.matchingLicense = null; - this.lastState = State.i; } @Override @@ -59,52 +57,18 @@ public String getId() { @Override public void reset() { enclosed.forEach(ILicense::reset); - this.lastState = State.i; this.matchingLicense = null; } @Override - public State matches(String line) { - State dflt = State.f; + public boolean matches(IHeaders headers) { for (ILicense license : enclosed) { - switch (license.matches(line)) { - case t: - this.matchingLicense = license; - lastState = State.t; - return State.t; - case i: - dflt = State.i; - break; - default: - // do nothing - break; + if (license.matches(headers)) { + matchingLicense = license; + return true; } } - lastState = dflt; - return dflt; - } - - @Override - public State currentState() { - if (lastState == State.t) { - return lastState; - } - for (ILicense license : enclosed) { - switch (license.currentState()) { - case t: - this.matchingLicense = license; - lastState = State.t; - return lastState; - case i: - lastState = State.i; - return lastState; - case f: - // do nothing; - break; - } - } - lastState = State.f; - return lastState; + return false; } @Override diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java index 113771b09..881ab4676 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java @@ -40,7 +40,7 @@ public class UnknownLicense implements ILicense { /** * Do not allow other constructions. */ - private UnknownLicense() { + UnknownLicense() { family = new ILicenseFamilyBuilder().setLicenseFamilyCategory("?????") .setLicenseFamilyName("Unknown license").build(); } @@ -56,18 +56,8 @@ public void reset() { } @Override - public State matches(String line) { - return State.f; - } - - @Override - public State finalizeState() { - return State.f; - } - - @Override - public State currentState() { - return State.f; + public boolean matches(IHeaders headers) { + return false; } @Override diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java index d15dd4258..466629520 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java @@ -59,10 +59,4 @@ public AbstractMatcherContainer(Collection enclosed) { public void reset() { enclosed.forEach(IHeaderMatcher::reset); } - - @Override - public State finalizeState() { - enclosed.forEach(IHeaderMatcher::finalizeState); - return currentState(); - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractSimpleMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractSimpleMatcher.java index 71852c075..6818990d7 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractSimpleMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractSimpleMatcher.java @@ -24,7 +24,6 @@ * {@code finalizeState()} method will convert {@code State.i} to {@code State.f}. */ public abstract class AbstractSimpleMatcher extends AbstractHeaderMatcher { - private State lastState; /** * Constructs the AbstractSimpleMatcher with the specified id. @@ -33,42 +32,11 @@ public abstract class AbstractSimpleMatcher extends AbstractHeaderMatcher { */ protected AbstractSimpleMatcher(String id) { super(id); - this.lastState = State.i; } - - /** - * Performs the actual match test. - * @param line the line to check. - * @return {@code true} if the line matches, {@code false} otherwise. - */ - abstract protected boolean doMatch(String line); - - @Override - public final State matches(String line) { - if (lastState == State.t) { - return lastState; - } - if (line != null && doMatch(line)) { - lastState = State.t; - } - return lastState; - } - + + @Override public void reset() { - lastState = State.i; - } - - @Override - public State finalizeState() { - if (lastState == State.i) { - lastState = State.f; - } - return lastState; - } - - @Override - public final State currentState() { - return lastState; + // do nothing. } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java index fc64f6e43..91b9fab29 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java @@ -21,6 +21,7 @@ import java.util.Collection; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; /** * A matcher that performs a logical {@code AND} across all the contained matchers. @@ -45,32 +46,13 @@ public AndMatcher(Collection enclosed) { } @Override - public State currentState() { - State dflt = State.t; + public boolean matches(IHeaders headers) { for (IHeaderMatcher matcher : enclosed) { - switch (matcher.currentState()) { - case f: - return State.f; - case i: - dflt = State.i; - break; - default: - // do nothing - break; + if (!matcher.matches(headers)) + { + return false; } } - return dflt; - } - - @Override - public State matches(String line) { - enclosed.stream().filter(x -> x.currentState() == State.i).forEach(x -> x.matches(line)); - return currentState(); - } - - @Override - public State finalizeState() { - enclosed.forEach(IHeaderMatcher::finalizeState); - return currentState(); + return true; } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java index a03798b4d..9dc1d019b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java @@ -22,6 +22,7 @@ import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; +import org.apache.rat.analysis.IHeaders; /** * Matches a typical Copyright header line only based on a regex pattern which @@ -105,12 +106,12 @@ public CopyrightMatcher(String id, String start, String stop, String owner) { } @Override - protected boolean doMatch(String line) { - String lowerLine = line.toLowerCase(); - if (lowerLine.contains("copyright") || lowerLine.contains("(c)") || line.contains("©")) { - Matcher matcher = COPYRIGHT_PATTERN.matcher(line); + public boolean matches(IHeaders headers) { + String lowerLine = headers.raw().toLowerCase(); + if (lowerLine.contains("copyright") || lowerLine.contains("(c)") || lowerLine.contains("©")) { + Matcher matcher = COPYRIGHT_PATTERN.matcher(headers.raw()); if (matcher.find()) { - String buffer = line.substring(matcher.end()); + String buffer = headers.raw().substring(matcher.end()); matcher = dateOwnerPattern.matcher(buffer); if (matcher.find() && matcher.start() == 0) { return true; diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java index ece1118f1..26d35dcc5 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java @@ -21,6 +21,8 @@ import java.util.Locale; import java.util.Objects; +import org.apache.rat.analysis.IHeaders; + /** * Accumulates all letters and numbers contained inside the header and compares * it to the full text of a given license (after reducing it to letters and @@ -38,12 +40,6 @@ public class FullTextMatcher extends AbstractSimpleMatcher { private final String fullText; - private final String firstLine; - - private boolean seenFirstLine; - - private final StringBuilder buffer = new StringBuilder(); - /** * Constructs the full text matcher with a unique random id and the specified text to match. * @param fullText the text to match @@ -59,15 +55,7 @@ public FullTextMatcher(String fullText) { */ public FullTextMatcher(String id, String fullText) { super(id); - Objects.requireNonNull(fullText, "fullText may not be null"); - int offset = fullText.indexOf('\n'); - if (offset == -1) { - offset = Math.min(DEFAULT_INITIAL_LINE_LENGTH, fullText.length()); - } - firstLine = prune(fullText.substring(0, offset)).toLowerCase(Locale.ENGLISH); this.fullText = prune(fullText).toLowerCase(Locale.ENGLISH); - buffer.setLength(0); - seenFirstLine = false; } /** @@ -89,44 +77,10 @@ public static String prune(String text) { } @Override - public boolean doMatch(String line) { - final String inputToMatch = prune(line).toLowerCase(Locale.ENGLISH); - if (seenFirstLine) { // Accumulate more input - buffer.append(inputToMatch); - } else { - int offset = inputToMatch.indexOf(firstLine); - if (offset >= 0) { - // we have a match, save the text starting with the match - buffer.append(inputToMatch.substring(offset)); - seenFirstLine = true; - // Drop out to check whether full text is matched - } else { - // we assume that the first line must appear in a single line - return false; // no more to do here - } - } - - if (buffer.length() >= fullText.length()) { // we have enough data to match - if (buffer.toString().contains(fullText)) { - return true; - } - // buffer contains first line but does not contain full text - // It's possible that the buffer contains the first line again - int offset = buffer.substring(1).indexOf(firstLine); - if (offset >= 0) { // first line found again - buffer.delete(0, offset); // reset buffer to the new start - } else { // buffer does not even contain first line, so cannot be used to match full text - reset(); - } + public boolean matches(IHeaders headers) { + if (headers.pruned().length() >= fullText.length()) { // we have enough data to match + return headers.pruned().contains(fullText); } return false; } - - @Override - public void reset() { - super.reset(); - buffer.setLength(0); - seenFirstLine = false; - } - } \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java index 8678f9257..ca5173e67 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java @@ -21,6 +21,7 @@ import java.util.Objects; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; /** * An IHeaderMatcher that reverses the result of an enclosed matcher. */ @@ -48,32 +49,12 @@ public NotMatcher(String id, IHeaderMatcher enclosed) { } @Override - public State matches(String line) { - enclosed.matches(line); - return currentState(); + public boolean matches(IHeaders headers) { + return !enclosed.matches(headers); } @Override public void reset() { enclosed.reset(); } - - @Override - public State finalizeState() { - enclosed.finalizeState(); - return currentState(); - } - - @Override - public State currentState() { - switch (enclosed.currentState()) { - case t: - return State.f; - case f: - return State.t; - default: - case i: - return State.i; - } - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java index 9b7bbae8a..c9117ff1a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java @@ -21,14 +21,13 @@ import java.util.Collection; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; /** * A matcher that performs a logical {@code OR} across all the contained matchers. */ public class OrMatcher extends AbstractMatcherContainer { - private State lastState; - /** * Constructs the matcher from the enclosed matchers. * @param enclosed the enclosed matchers. @@ -44,52 +43,16 @@ public OrMatcher(Collection enclosed) { */ public OrMatcher(String id, Collection enclosed) { super(id, enclosed); - lastState = State.i; - } - - @Override - public State matches(String line) { - if (lastState == State.t) { - return State.t; - } - for (IHeaderMatcher matcher : enclosed) { - switch (matcher.matches(line)) { - case t: - lastState = State.t; - return lastState; - case f: - case i: - lastState = State.i; - } - } - return lastState; } @Override - public State currentState() { - if (lastState == State.t) { - return lastState; - } + public boolean matches(IHeaders headers) { for (IHeaderMatcher matcher : enclosed) { - switch (matcher.currentState()) { - case t: - lastState = State.t; - return lastState; - case i: - lastState = State.i; - return lastState; - case f: - // do nothing; - break; + if (matcher.matches(headers)) { + return true; } + } - lastState = State.f; - return lastState; - } - - @Override - public void reset() { - super.reset(); - lastState = State.i; + return false; } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java index 5766b5257..a0311c433 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java @@ -27,6 +27,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; /** * Defines a factory to produce matchers for an SPDX tag. SPDX tag is of the format @@ -124,8 +125,8 @@ public class Match extends AbstractSimpleMatcher { } @Override - protected boolean doMatch(String line) { - return SPDXMatcherFactory.this.check(line, this); + public boolean matches(IHeaders headers) { + return SPDXMatcherFactory.this.check(headers.raw(), this); } @Override diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index 641f7ab43..f7a9ad40c 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -20,6 +20,8 @@ import java.util.regex.Pattern; +import org.apache.rat.analysis.IHeaders; + /** * A simple regular expression matching IHeaderMatcher */ @@ -45,7 +47,7 @@ public SimpleRegexMatcher(String id, Pattern pattern) { } @Override - public boolean doMatch(String line) { - return pattern.matcher(line).find(); + public boolean matches(IHeaders headers) { + return pattern.matcher(headers.raw()).find(); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java index f7ae6ef90..61085ad51 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java @@ -19,6 +19,7 @@ package org.apache.rat.analysis.matchers; import org.apache.commons.lang3.StringUtils; +import org.apache.rat.analysis.IHeaders; /** * A simple text matching IHeaderMatcher implementation. @@ -48,7 +49,7 @@ public SimpleTextMatcher(String id, String pattern) { } @Override - public boolean doMatch(String line) { - return line.contains(pattern); + public boolean matches(IHeaders headers) { + return headers.raw().contains(pattern); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java index 17918096a..3c047bc58 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java @@ -21,6 +21,7 @@ import java.util.Map; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; /** * A reference matching Matcher builder. @@ -104,21 +105,9 @@ public void reset() { } @Override - public State matches(String line) { + public boolean matches(IHeaders headers) { checkProxy(); - return wrapped.matches(line); - } - - @Override - public State currentState() { - checkProxy(); - return wrapped.currentState(); - } - - @Override - public State finalizeState() { - checkProxy(); - return wrapped.finalizeState(); + return wrapped.matches(headers); } } 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 40bbe20ee..750c8d179 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 @@ -22,6 +22,8 @@ import java.util.SortedSet; import java.util.TreeSet; +import org.apache.rat.analysis.IHeaders; + /** * Class to take a set of ILicenses and collection of approved license categories and extract Subsets. */ @@ -166,8 +168,8 @@ public void reset() { } @Override - public State matches(String line) { - return State.f; + public boolean matches(IHeaders headers) { + return false; } @Override @@ -195,16 +197,6 @@ public String getName() { return searchFamily.getFamilyName(); } - @Override - public State finalizeState() { - return State.f; - } - - @Override - public State currentState() { - return State.f; - } - }; return search(target, licenses); } 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 18e4f7609..86c4be012 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 @@ -22,6 +22,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; /** * A simple implementation of ILicense. @@ -82,18 +83,8 @@ public void reset() { } @Override - public State matches(String line) { - return matcher.matches(line); - } - - @Override - public State finalizeState() { - return matcher.finalizeState(); - } - - @Override - public State currentState() { - return matcher.currentState(); + public boolean matches(IHeaders headers) { + return matcher.matches(headers); } @Override diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java index 3d5f87ec6..7a4e79ee7 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java @@ -27,7 +27,6 @@ import java.io.StringWriter; import java.util.Arrays; -import org.apache.rat.analysis.IHeaderMatcher.State; import org.apache.rat.document.IDocumentAnalyser; import org.apache.rat.document.impl.MonolithicFileDocument; import org.apache.rat.license.ILicense; @@ -41,13 +40,7 @@ public class AnalyserFactoryTest { - private static ILicense MATCHES_NOTHING_MATCHER = mock(ILicense.class); - - static { - when(MATCHES_NOTHING_MATCHER.matches(any())).thenReturn(State.f); - when(MATCHES_NOTHING_MATCHER.currentState()).thenReturn(State.f); - when(MATCHES_NOTHING_MATCHER.finalizeState()).thenReturn(State.f); - } + private static ILicense MATCHES_NOTHING_MATCHER = new UnknownLicense(); private StringWriter out; private SimpleXmlClaimReporter reporter; 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 e231ad097..53374e036 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 @@ -38,8 +38,6 @@ public void isFinished() throws Exception { final Document subject = new TestingLocation("subject"); ILicense matcher = new TestingLicense(); HeaderCheckWorker worker = new HeaderCheckWorker(new StringReader(""), matcher, subject); - assertFalse(worker.isFinished()); worker.read(); - assertTrue(worker.isFinished()); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java index ad17c909b..0a22ad65e 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java @@ -31,7 +31,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.Defaults; -import org.apache.rat.analysis.IHeaderMatcher.State; +import org.apache.rat.analysis.HeaderCheckWorker; +import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.matchers.FullTextMatcher; import org.apache.rat.api.MetaData; import org.apache.rat.license.ILicense; @@ -115,13 +116,8 @@ public void testMatchProcessing(String id, String familyPattern, String name, St private boolean processText(ILicense license, String text) throws IOException { try (BufferedReader in = new BufferedReader(new StringReader(text))) { - String line; - while (null != (line = in.readLine())) { - if (license.matches(line) == State.t) { - return true; - } - } - return license.finalizeState().asBoolean(); + IHeaders headers = HeaderCheckWorker.readHeader(in,HeaderCheckWorker.DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES); + return license.matches(headers); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java index 57eb1b9a5..9cff878cd 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/DirectoryScanner.java @@ -25,7 +25,8 @@ import java.io.File; import org.apache.commons.io.IOUtils; -import org.apache.rat.analysis.IHeaderMatcher.State; +import org.apache.rat.analysis.HeaderCheckWorker; +import org.apache.rat.analysis.IHeaders; import org.apache.rat.license.ILicense; import org.apache.rat.test.utils.Resources; import org.junit.jupiter.api.Test; @@ -48,18 +49,12 @@ public static void testFilesInDir(String directory, ILicense license, boolean ex fail("No files found under " + directory); } for (File f : resourceFiles) { - BufferedReader br = null; - try { - boolean result = false; - br = Resources.getBufferedReader(f); - String line; - while (!result && (line = br.readLine()) != null) { - result = license.matches(line) == State.t; - } + try (BufferedReader br = Resources.getBufferedReader(f)){ + IHeaders headers = HeaderCheckWorker.readHeader(br, HeaderCheckWorker.DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES); + boolean result = license.matches(headers); assertEquals(expected, result, f.toString()); } finally { license.reset(); - IOUtils.closeQuietly(br); } } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AbstractMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AbstractMatcherTest.java new file mode 100644 index 000000000..3b38d0502 --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AbstractMatcherTest.java @@ -0,0 +1,65 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + */ +package org.apache.rat.analysis.matchers; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +import java.util.Locale; + +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; + +public class AbstractMatcherTest { + + private IHeaders dummyHeader = makeHeaders(null, null); + + protected void assertValues(IHeaderMatcher target, boolean... values) { + for (int i = 0; i < values.length; i++) { + final int idx = i; + assertEquals(values[i], target.matches(dummyHeader), () -> String.format("Position %s", idx)); + } + } + + public static IHeaders makeHeaders(String raw, String pruned) { + return new IHeaders() { + + @Override + public String raw() { + if (raw == null) { + throw new UnsupportedOperationException("Should not be called"); + } + return raw; + } + + @Override + public String pruned() { + if (pruned == null) { + throw new UnsupportedOperationException("Should not be called"); + } + return FullTextMatcher.prune(pruned).toLowerCase(Locale.ENGLISH); + } + + @Override + public String toString() { + return "AbstractMatcherTest"; + } + }; + } + +} diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java index a8ac49994..643665bab 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java @@ -23,56 +23,20 @@ import java.util.Arrays; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaderMatcher.State; +import org.apache.rat.analysis.IHeaders; import org.apache.rat.testhelpers.TestingMatcher; import org.junit.jupiter.api.Test; - -public class AndMatcherTest { - - private void assertValues(IHeaderMatcher target, State hello, State world, State finalize) { - assertEquals(State.i, target.currentState()); - assertEquals(hello, target.matches("hello")); - assertEquals(hello, target.currentState()); - assertEquals(world, target.matches("world")); - assertEquals(world, target.currentState()); - assertEquals(finalize, target.finalizeState()); - assertEquals(finalize, target.currentState()); - } +public class AndMatcherTest extends AbstractMatcherTest { @Test public void trueTest() { - IHeaderMatcher one = new TestingMatcher("one", true); - IHeaderMatcher two = new TestingMatcher("two", false, true); - AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two)); - assertValues(target, State.i, State.t, State.t); - target.reset(); - assertEquals(State.i, one.currentState()); - assertEquals(State.i, two.currentState()); - assertEquals(State.i, target.currentState()); - } - @Test - public void falseTest() { - IHeaderMatcher one = new TestingMatcher("one", true); - IHeaderMatcher two = new TestingMatcher("two", false, false); - AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two)); - assertValues(target, State.i, State.i, State.f); - target.reset(); - assertEquals(State.i, one.currentState()); - assertEquals(State.i, two.currentState()); - assertEquals(State.i, target.currentState()); - } - - @Test - public void indeterminentTest() { - IHeaderMatcher one = new TestingMatcher("one", false, false); - IHeaderMatcher two = new TestingMatcher("two", false, false); + IHeaderMatcher one = new TestingMatcher("one", true, true, false, false); + // only need 2 entries because when one is false two test does not get called. + IHeaderMatcher two = new TestingMatcher("two", true, false); AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two)); - assertValues(target, State.i, State.i, State.f); + assertValues(target, true, false, false, false); target.reset(); - assertEquals(State.i, one.currentState()); - assertEquals(State.i, two.currentState()); - assertEquals(State.i, target.currentState()); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/CopyrightMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/CopyrightMatcherTest.java index 32f6820ee..b0c915905 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/CopyrightMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/CopyrightMatcherTest.java @@ -20,6 +20,7 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import java.util.ArrayList; import java.util.Arrays; @@ -28,7 +29,8 @@ import java.util.Set; import java.util.stream.Stream; -import org.apache.rat.analysis.IHeaderMatcher.State; +import org.apache.rat.analysis.HeaderCheckWorker; +import org.apache.rat.analysis.IHeaders; import org.junit.jupiter.params.ParameterizedTest; import org.junit.jupiter.params.provider.Arguments; import org.junit.jupiter.params.provider.MethodSource; @@ -95,10 +97,9 @@ public void testPass(String testName, String start, String stop, String owner, S verify(testName, pass, fail); CopyrightMatcher matcher = new CopyrightMatcher(start, stop, owner); for (String[] target : pass) { - assertEquals(State.i, matcher.currentState(), ()->String.format("%s:%s failed", testName, target[NAME])); - assertEquals(State.t, matcher.matches(target[TEXT]), ()->String.format("%s:%s failed", testName, target[NAME])); + IHeaders headers = AbstractMatcherTest.makeHeaders(target[TEXT],null); + assertTrue(matcher.matches(headers), ()->String.format("%s:%s failed", testName, target[NAME])); matcher.reset(); - assertEquals(State.i, matcher.currentState(),()->String.format("%s:%s failed", testName, target[NAME])); } } @@ -109,11 +110,9 @@ public void testFail(String testName, String start, String stop, String owner, S verify(testName, pass, fail); CopyrightMatcher matcher = new CopyrightMatcher(start, stop, owner); for (String[] target : fail) { - assertEquals( State.i, matcher.currentState(), ()->String.format("%s:%s passed", testName, target[NAME])); - assertEquals( State.i, matcher.matches(target[TEXT]), ()->String.format("%s:%s passed", testName, target[NAME])); - assertEquals( State.f, matcher.finalizeState(), ()->String.format("%s:%s passed", testName, target[NAME])); + IHeaders headers = AbstractMatcherTest.makeHeaders(target[TEXT],null); + assertFalse( matcher.matches(headers), String.format("%s:%s passed", testName, target[NAME])); matcher.reset(); - assertEquals( State.i, matcher.currentState(), ()->String.format("%s:%s passed", testName, target[NAME])); } } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java index 03a3251c9..c029513ae 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java @@ -24,7 +24,10 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.apache.rat.analysis.IHeaderMatcher.State; +import java.util.Locale; + +import org.apache.commons.lang3.tuple.Pair; +import org.apache.rat.analysis.IHeaders; public class FullTextMatcherTest { @@ -34,43 +37,11 @@ public class FullTextMatcherTest { public void setup() { target.reset(); } - + @Test public void testMatch() { - assertEquals( State.i, target.currentState()); - assertEquals( State.i, target.matches("what in the world")); - assertEquals( State.i, target.currentState()); - assertEquals( State.t, target.matches("hello world")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.finalizeState()); - assertEquals( State.t, target.currentState()); - target.reset(); - assertEquals( State.i, target.currentState()); - } - - @Test - public void testNoMatch() { - assertEquals( State.i, target.currentState()); - assertEquals( State.i, target.matches("what in the world")); - assertEquals( State.i, target.currentState()); - assertEquals( State.i, target.matches("hello there")); - assertEquals( State.i, target.currentState()); - assertEquals( State.f, target.finalizeState()); - assertEquals( State.f, target.currentState()); - target.reset(); - assertEquals( State.i, target.currentState()); - } - - @Test - public void testTrueIsAlwaysTrue() { - assertEquals( State.i, target.currentState()); - assertEquals( State.t, target.matches("hello world")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.matches("A non matching line")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.finalizeState()); - assertEquals( State.t, target.currentState()); - target.reset(); - assertEquals( State.i, target.currentState()); + assertEquals(false, target.matches(AbstractMatcherTest.makeHeaders(null, "what in the world"))); + assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders(null, "hello world"))); + assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders(null, "HELLO world"))); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/NotMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/NotMatcherTest.java index 806b6573d..4c8f416cb 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/NotMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/NotMatcherTest.java @@ -21,43 +21,16 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaderMatcher.State; import org.apache.rat.testhelpers.TestingMatcher; import org.junit.jupiter.api.Test; -public class NotMatcherTest { - - private void assertValues(IHeaderMatcher target, State hello, State world, State finalize) { - assertEquals(State.i, target.currentState()); - assertEquals( hello, target.matches("hello"), "hello match"); - assertEquals( hello, target.currentState(), "hello current"); - assertEquals(world, target.matches("world"), "world match"); - assertEquals( world, target.currentState(), "world current"); - assertEquals(finalize, target.finalizeState(), "finalize match"); - assertEquals(finalize, target.currentState(), "finalize current"); - } +public class NotMatcherTest extends AbstractMatcherTest { @Test - public void testTrue() { - IHeaderMatcher one = new TestingMatcher("one", true); + public void test() { + IHeaderMatcher one = new TestingMatcher("one", true, false); NotMatcher target = new NotMatcher("Testing", one); - assertValues(target, State.f, State.f, State.f); - - one = new TestingMatcher("one", false, true); - target = new NotMatcher("Testing", one); - assertValues(target, State.i, State.f, State.f); - target.reset(); - assertEquals(State.i, target.currentState()); + assertValues(target, false, true); } - @Test - public void testFalse() { - TestingMatcher one = new TestingMatcher("one", false, false); - one.finalState = State.t; - NotMatcher target = new NotMatcher("Testing", one); - assertValues(target, State.i, State.i, State.f); - target.reset(); - assertEquals(State.i, target.currentState()); - - } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/OrMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/OrMatcherTest.java index 81478b37b..0b693be3e 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/OrMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/OrMatcherTest.java @@ -23,55 +23,18 @@ import java.util.Arrays; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaderMatcher.State; import org.apache.rat.testhelpers.TestingMatcher; import org.junit.jupiter.api.Test; -public class OrMatcherTest { - - private void assertValues(IHeaderMatcher target, State hello, State world, State finalize) { - assertEquals(State.i, target.currentState()); - assertEquals( hello, target.matches("hello"), "hello match"); - assertEquals( hello, target.currentState(), "hello current"); - assertEquals(world, target.matches("world"), "world match"); - assertEquals( world, target.currentState(), "world current"); - assertEquals(finalize, target.finalizeState(), "finalize match"); - assertEquals(finalize, target.currentState(), "finalize current"); - } +public class OrMatcherTest extends AbstractMatcherTest { + @Test public void trueTest() { - IHeaderMatcher one = new TestingMatcher("one", false, false); - IHeaderMatcher two = new TestingMatcher("two", false, true); - OrMatcher target = new OrMatcher("Testing", Arrays.asList(one, two)); - assertValues(target, State.i, State.t, State.t); - target.reset(); - assertEquals(State.i, one.currentState()); - assertEquals(State.i, two.currentState()); - assertEquals(State.i, target.currentState()); - } - - @Test - public void falseTest() { - IHeaderMatcher one = new TestingMatcher("one", false, false); - IHeaderMatcher two = new TestingMatcher("two", false, false); - OrMatcher target = new OrMatcher("Testing", Arrays.asList(one, two)); - assertValues(target, State.i, State.i, State.f); - target.reset(); - assertEquals(State.i, one.currentState()); - assertEquals(State.i, two.currentState()); - assertEquals(State.i, target.currentState()); - } - - @Test - public void indeterminentTest() { - IHeaderMatcher one = new TestingMatcher("one", false, false); - IHeaderMatcher two = new TestingMatcher("two", false, false); + IHeaderMatcher one = new TestingMatcher("one", false, false, true, true); + IHeaderMatcher two = new TestingMatcher("two", false, true, false, true); OrMatcher target = new OrMatcher("Testing", Arrays.asList(one, two)); - assertValues(target, State.i, State.i, State.f); + assertValues(target, false, true, true, true); target.reset(); - assertEquals(State.i, one.currentState()); - assertEquals(State.i, two.currentState()); - assertEquals(State.i, target.currentState()); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java index 124ed357b..1145058d6 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java @@ -21,7 +21,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaderMatcher.State; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -36,51 +35,8 @@ public void setup() { @Test public void testMatch() { - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("SPDX-License-Identifier: Apache-2")); - assertEquals(State.i, target.currentState()); - assertEquals(State.t, target.matches("SPDX-License-Identifier: hello")); - assertEquals(State.t, target.currentState()); - assertEquals(State.t, target.finalizeState()); - assertEquals(State.t, target.currentState()); + assertEquals(false, target.matches(AbstractMatcherTest.makeHeaders("SPDX-License-Identifier: Apache-2", null))); + assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders("SPDX-License-Identifier: hello", null))); target.reset(); - assertEquals(State.i, target.currentState()); - } - - @Test - public void testNoMatch() { - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("SPDX-License-Identifier: Apache-2")); - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("SPDX-License-Identifier: MIT")); - assertEquals(State.i, target.currentState()); - assertEquals(State.f, target.finalizeState()); - assertEquals(State.f, target.currentState()); - target.reset(); - assertEquals(State.i, target.currentState()); - } - - @Test - public void testTrueIsAlwaysTrue() { - assertEquals(State.i, target.currentState()); - assertEquals(State.t, target.matches("SPDX-License-Identifier: hello")); - assertEquals(State.t, target.currentState()); - assertEquals(State.t, target.matches("SPDX-License-Identifier: Apache-2")); - assertEquals(State.t, target.currentState()); - assertEquals(State.t, target.finalizeState()); - assertEquals(State.t, target.currentState()); - target.reset(); - assertEquals(State.i, target.currentState()); - } - - @Test - public void testResetClearsLastMatch() { - - assertEquals(State.i, target.currentState()); - assertEquals(State.t, target.matches("SPDX-License-Identifier: hello")); - assertEquals(State.t, target.currentState()); - target.reset(); - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("Something weird"));; } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java index b836f6470..3da63c337 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java @@ -19,8 +19,6 @@ package org.apache.rat.analysis.matchers; import static org.junit.jupiter.api.Assertions.assertEquals; - -import org.apache.rat.analysis.IHeaderMatcher.State; import org.junit.jupiter.api.Test; public class SimpleCopyrightTests { @@ -29,15 +27,8 @@ public class SimpleCopyrightTests { @Test public void testTrueIsAlwaysTrue() { - - assertEquals( State.i, target.currentState()); - assertEquals( State.t, target.matches("hello Copyright 1999")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.matches("A non matching line")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.finalizeState()); - assertEquals( State.t, target.currentState()); + assertEquals( true, target.matches(AbstractMatcherTest.makeHeaders("hello Copyright 1999", null))); + assertEquals( false, target.matches(AbstractMatcherTest.makeHeaders("A non matching line",null))); target.reset(); - assertEquals( State.i, target.currentState()); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleRegexMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleRegexMatcherTest.java index 53dee7607..0c09e89ef 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleRegexMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleRegexMatcherTest.java @@ -25,8 +25,6 @@ import java.util.regex.Pattern; -import org.apache.rat.analysis.IHeaderMatcher.State; - public class SimpleRegexMatcherTest { SimpleRegexMatcher target = new SimpleRegexMatcher(Pattern.compile("hello\\sworld")); @@ -37,41 +35,9 @@ public void setup() { } @Test - public void testMatch() { - assertEquals( State.i, target.currentState()); - assertEquals( State.i, target.matches("what in the world")); - assertEquals( State.i, target.currentState()); - assertEquals( State.t, target.matches("hello world")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.finalizeState()); - assertEquals( State.t, target.currentState()); - target.reset(); - assertEquals( State.i, target.currentState()); - } - - @Test - public void testNoMatch() { - assertEquals( State.i, target.currentState()); - assertEquals( State.i, target.matches("what in the world")); - assertEquals( State.i, target.currentState()); - assertEquals( State.i, target.matches("hello there")); - assertEquals( State.i, target.currentState()); - assertEquals( State.f, target.finalizeState()); - assertEquals( State.f, target.currentState()); - target.reset(); - assertEquals( State.i, target.currentState()); - } - - @Test - public void testTrueIsAlwaysTrue() { - assertEquals( State.i, target.currentState()); - assertEquals( State.t, target.matches("hello world")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.matches("A non matching line")); - assertEquals( State.t, target.currentState()); - assertEquals( State.t, target.finalizeState()); - assertEquals( State.t, target.currentState()); + public void test() { + assertEquals( false, target.matches(AbstractMatcherTest.makeHeaders("what in the world",null))); + assertEquals( true, target.matches(AbstractMatcherTest.makeHeaders("hello world",null))); target.reset(); - assertEquals( State.i, target.currentState()); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java index 2ad73d6bf..567e97960 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java @@ -20,7 +20,6 @@ import static org.junit.jupiter.api.Assertions.assertEquals; -import org.apache.rat.analysis.IHeaderMatcher.State; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -35,54 +34,9 @@ public void setup() { @Test public void testMatch() { - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("what in the world")); - assertEquals(State.i, target.currentState()); - assertEquals(State.t, target.matches("hello world")); - assertEquals(State.t, target.currentState()); - assertEquals(State.t, target.finalizeState()); - assertEquals(State.t, target.currentState()); + assertEquals(false, target.matches(AbstractMatcherTest.makeHeaders("what in the world",null))); + assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders("hello world",null))); target.reset(); - assertEquals(State.i, target.currentState()); } - @Test - public void testNoMatch() { - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("what in the world")); - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("hell o'there")); - assertEquals(State.i, target.currentState()); - assertEquals(State.f, target.finalizeState()); - assertEquals(State.f, target.currentState()); - target.reset(); - assertEquals(State.i, target.currentState()); - } - - @Test - public void testTrueIsAlwaysTrue() { - assertEquals(State.i, target.currentState()); - assertEquals(State.t, target.matches("hello world")); - assertEquals(State.t, target.currentState()); - assertEquals(State.t, target.matches("A non matching line")); - assertEquals(State.t, target.currentState()); - assertEquals(State.t, target.finalizeState()); - assertEquals(State.t, target.currentState()); - target.reset(); - assertEquals(State.i, target.currentState()); - } - - @Test - public void testIndeterminent() { - target = new SimpleTextMatcher("not a match"); - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("hello world")); - assertEquals(State.i, target.currentState()); - assertEquals(State.i, target.matches("A non matching line")); - assertEquals(State.i, target.currentState()); - assertEquals(State.f, target.finalizeState()); - assertEquals(State.f, target.currentState()); - target.reset(); - assertEquals(State.i, target.currentState()); - } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java index 0593b3415..462c110de 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java @@ -33,7 +33,6 @@ import org.apache.commons.io.filefilter.HiddenFileFilter; import org.apache.rat.ConfigurationException; import org.apache.rat.ReportConfiguration; -import org.apache.rat.analysis.IHeaderMatcher.State; import org.apache.rat.api.MetaData; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -105,7 +104,7 @@ public void standardReport() throws Exception { public void testNoLicense() throws Exception { final ILicense mockLicense = mock(ILicense.class); - when(mockLicense.matches(any())).thenReturn(State.t); + when(mockLicense.matches(any())).thenReturn(true); when(mockLicense.getLicenseFamily()).thenReturn(family); final ClaimStatistic statistic = new ClaimStatistic(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java index 2af06f330..12ccc8e11 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java @@ -102,6 +102,7 @@ public void baseReport() throws Exception { XPath xPath = XPathFactory.newInstance().newXPath(); Document doc = XmlUtils.toDom(new ByteArrayInputStream(out.toByteArray())); + XmlUtils.printDocument(System.out, doc); XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/ILoggerFactory.java", "QOS", null, "standard"); XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Image.png", null, null, "binary"); XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/LICENSE", null, null, "notice"); diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java index 53c0844c9..ea3bd1ee9 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java @@ -20,6 +20,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.IHeaders; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -135,18 +136,8 @@ public void reset() { } @Override - public State matches(String line) { - return matcher.matches(line); - } - - @Override - public State finalizeState() { - return matcher.finalizeState(); - } - - @Override - public State currentState() { - return matcher.currentState(); + public boolean matches(IHeaders headers) { + return matcher.matches(headers); } @Override diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java index 70722000c..b50711b4d 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java @@ -21,16 +21,15 @@ import java.util.LinkedList; import java.util.Queue; +import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.matchers.AbstractHeaderMatcher; /** * An Matcher for testing. */ public class TestingMatcher extends AbstractHeaderMatcher { - private State lastState; private final boolean[] initialResults; private Queue results; - public State finalState = State.f; /** * Constructs a matcher with an ID of "dfltMtch" that does not match anyting. @@ -70,35 +69,15 @@ public TestingMatcher(String id, boolean... results) { } @Override - public final State matches(String line) { - if (lastState == State.t) { - return lastState; - } - if (line != null && results.poll()) { - lastState = State.t; - } - return lastState; + public final boolean matches(IHeaders headers) { + return results.poll(); } @Override public void reset() { - lastState = State.i; results.clear(); for (boolean b : initialResults) { this.results.add(b); } } - - @Override - public State finalizeState() { - if (lastState == State.i) { - lastState = finalState; - } - return lastState; - } - - @Override - public final State currentState() { - return lastState; - } } \ No newline at end of file diff --git a/apache-rat-tasks/src/test/java/org/example/Matcher.java b/apache-rat-tasks/src/test/java/org/example/Matcher.java index 168f1e8f3..26504091b 100644 --- a/apache-rat-tasks/src/test/java/org/example/Matcher.java +++ b/apache-rat-tasks/src/test/java/org/example/Matcher.java @@ -16,6 +16,7 @@ */ package org.example; +import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.matchers.AbstractSimpleMatcher; public class Matcher extends AbstractSimpleMatcher { @@ -24,7 +25,7 @@ public Matcher() { } @Override - public boolean doMatch(String line) { + public boolean matches(IHeaders headers) { return true; } diff --git a/apache-rat-tasks/src/test/resources/antunit/report-junit.xml b/apache-rat-tasks/src/test/resources/antunit/report-junit.xml index 76cefe572..d27b62ff4 100644 --- a/apache-rat-tasks/src/test/resources/antunit/report-junit.xml +++ b/apache-rat-tasks/src/test/resources/antunit/report-junit.xml @@ -173,6 +173,7 @@ package org.example; import org.apache.rat.analysis.matchers.AbstractSimpleMatcher; +import org.apache.rat.analysis.IHeaders; public class InlineMatcher extends AbstractSimpleMatcher { public InlineMatcher() { @@ -180,7 +181,7 @@ public class InlineMatcher extends AbstractSimpleMatcher { } @Override - public boolean doMatch(String line) { + public boolean matches(IHeaders headers) { return true; } } diff --git a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml index fa7d1a1ec..0dee34862 100644 --- a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml +++ b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml @@ -453,6 +453,7 @@ SPDX-License-Identifier: Apache-2.0 Date: Thu, 2 Nov 2023 18:32:17 +0100 Subject: [PATCH 02/77] fixed IO error --- apache-rat-core/src/test/java/org/apache/rat/ReportTest.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java index 8632e0294..0636ed77e 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java @@ -49,7 +49,7 @@ public void parseExclusionsForCLIUsage() { public void testDefaultConfiguration() throws ParseException, IOException { String[] empty = {}; CommandLine cl = new DefaultParser().parse(Report.buildOptions(), empty); - ReportConfiguration config = Report.createConfiguration("", cl); + ReportConfiguration config = Report.createConfiguration(".", cl); ReportConfigurationTest.validateDefault(config); } From 4e2859f6ae38dfaf0c3c3db0746d0aeaa3caf081 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Fri, 22 Mar 2024 13:23:51 +0100 Subject: [PATCH 03/77] cleaned up code --- .../rat/analysis/DefaultAnalyserFactory.java | 3 +- .../rat/analysis/HeaderCheckWorker.java | 68 +++++++++---------- .../analysis/matchers/FullTextMatcher.java | 15 ++-- .../impl/xml/SimpleXmlClaimReporter.java | 26 +++---- .../org/apache/rat/utils/ReportingSet.java | 51 +++++++------- 5 files changed, 77 insertions(+), 86 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java index 06cbe8d3a..3af84ae07 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java @@ -30,7 +30,6 @@ import org.apache.rat.document.impl.guesser.NoteGuesser; import org.apache.rat.license.ILicense; import org.apache.rat.utils.Log; -import org.apache.rat.utils.Log.Level; /** * Creates default analysers. @@ -39,7 +38,7 @@ public class DefaultAnalyserFactory { /** * Creates a DocumentAnalyser from a collection of ILicenses. - * @param licenses The licenses to use in the Analyser. + * @param licenses The licenses to use in the Analyser. * @return A document analyser that uses the provides licenses. */ public static IDocumentAnalyser createDefaultAnalyser(Log log, Collection 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 934886c54..7285d95ac 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 @@ -24,7 +24,6 @@ import java.util.Locale; import java.util.Objects; -import org.apache.commons.io.IOUtils; import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.matchers.FullTextMatcher; import org.apache.rat.api.Document; @@ -32,15 +31,16 @@ import org.apache.rat.license.ILicense; /** - * Reads from a stream to check license. - *

- * Note that this class is not thread safe. - *

+ * Reads from a stream to check license.

Note that this + * class is not thread safe.

*/ public class HeaderCheckWorker { - /* TODO revisit this class. It is only used in one place and can be moved inline as the DocumentHeaderAnalyser states. - * However, it may also be possible to make the entire set threadsafe so that multiple files can be checked simultaneously. + /* + * TODO revisit this class. It is only used in one place and can be moved inline + * as the DocumentHeaderAnalyser states. However, it may also be possible to + * make the entire set threadsafe so that multiple files can be checked + * simultaneously. */ /** * The default number of header lines to read while looking for the license @@ -53,44 +53,44 @@ public class HeaderCheckWorker { private final ILicense license; private final Document document; - /** * Read the input and perform the header check. - * + * * @throws RatHeaderAnalysisException on IO Exception. - * @throws IOException + * @throws IOException */ public static IHeaders readHeader(BufferedReader reader, int numberOfLines) throws IOException { final StringBuilder headers = new StringBuilder(); - int headerLinesRead=0; + int headerLinesRead = 0; String line; - - while (headerLinesRead < numberOfLines && (line = reader.readLine()) != null) { - headers.append(line).append("\n"); + + while (headerLinesRead < numberOfLines && (line = reader.readLine()) != null) { + headers.append(line).append("\n"); + } + final String raw = headers.toString(); + final String pruned = FullTextMatcher.prune(raw).toLowerCase(Locale.ENGLISH); + return new IHeaders() { + @Override + public String raw() { + return raw; } - final String raw = headers.toString(); - final String pruned = FullTextMatcher.prune(raw).toLowerCase(Locale.ENGLISH); - return new IHeaders() { - @Override - public String raw() { - return raw; - } - @Override - public String pruned() { - return pruned; - } - - public String toString() { - return "HeaderCheckWorker"; - } - }; + @Override + public String pruned() { + return pruned; + } + + @Override + public String toString() { + return "HeaderCheckWorker"; + } + }; } - + /** * Convenience constructor wraps given Reader in a * BufferedReader. - * + * * @param reader The reader on the document. not null. * @param license The license to check against. not null. * @param name The document that is being checked. possibly null @@ -101,7 +101,7 @@ public HeaderCheckWorker(Reader reader, final ILicense license, final Document n /** * Constructs a check worker for the license against the specified document. - * + * * @param reader The reader on the document. not null. * @param numberOfRetainedHeaderLine the maximum number of lines to read to find * the license information. @@ -123,7 +123,7 @@ public HeaderCheckWorker(Reader reader, int numberOfRetainedHeaderLine, final IL /** * Read the input and perform the header check. - * + * * @throws RatHeaderAnalysisException on IO Exception. */ public void read() throws RatHeaderAnalysisException { diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java index 26d35dcc5..6b121af7e 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java @@ -19,7 +19,6 @@ package org.apache.rat.analysis.matchers; import java.util.Locale; -import java.util.Objects; import org.apache.rat.analysis.IHeaders; @@ -28,20 +27,16 @@ * it to the full text of a given license (after reducing it to letters and * numbers as well). * - *

- * The text comparison is case insensitive but assumes only characters in the - * US-ASCII charset are being matched. - *

+ *

The text comparison is case insensitive but assumes only characters in + * the US-ASCII charset are being matched.

*/ public class FullTextMatcher extends AbstractSimpleMatcher { - // Number of match characters assumed to be present on first line - private static final int DEFAULT_INITIAL_LINE_LENGTH = 20; - private final String fullText; /** - * Constructs the full text matcher with a unique random id and the specified text to match. + * Constructs the full text matcher with a unique random id and the specified + * text to match. * @param fullText the text to match */ public FullTextMatcher(String fullText) { @@ -60,7 +55,7 @@ public FullTextMatcher(String id, String fullText) { /** * Removes everything except letter or digit from text. - * + * * @param text The text to remove extra chars from. * @return the pruned text. */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java index 43185931c..085a8ccc9 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java @@ -15,19 +15,18 @@ * 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.impl.xml; +import java.io.IOException; +import java.util.Calendar; + import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; import org.apache.rat.api.RatException; import org.apache.rat.report.AbstractReport; import org.apache.rat.report.xml.writer.IXmlWriter; -import org.apache.rat.report.xml.writer.impl.base.XmlWriter; - -import java.io.IOException; -import java.util.Calendar; public class SimpleXmlClaimReporter extends AbstractReport { private static final String RAT_REPORT = "rat-report"; @@ -46,18 +45,16 @@ public SimpleXmlClaimReporter(final IXmlWriter writer) { this.writer = writer; } - /** * Writes a single claim to the XML file. * @param pPredicate The claims predicate. * @param pObject The claims object. - * @param pLiteral Whether to write the object as an element (true), - * or an attribute (false). + * @param pLiteral Whether to write the object as an element (true), or an + * attribute (false). * @throws IOException An I/O error occurred while writing the claim. * @throws RatException Another error occurred while writing the claim. */ - protected void writeClaim(String pPredicate, String pObject, boolean pLiteral) - throws IOException, RatException { + protected void writeClaim(String pPredicate, String pObject, boolean pLiteral) throws IOException, RatException { if (pLiteral) { writer.openElement(pPredicate).content(pObject).closeElement(); } else { @@ -76,8 +73,7 @@ public void report(final Document subject) throws RatException { writer.openElement("resource").attribute(NAME, subject.getName()); writeDocumentClaims(subject); } catch (IOException e) { - throw new RatException("XML writing failure: " + e.getMessage() - + " subject: " + subject, e); + throw new RatException("XML writing failure: " + e.getMessage() + " subject: " + subject, e); } } @@ -128,10 +124,8 @@ private void writeDocumentCategory(final MetaData metaData) throws IOException, @Override public void startReport() throws RatException { try { - writer.openElement(RAT_REPORT) - .attribute(TIMESTAMP, - DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT - .format(Calendar.getInstance())); + writer.openElement(RAT_REPORT).attribute(TIMESTAMP, + DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(Calendar.getInstance())); } catch (IOException e) { throw new RatException("Cannot open start element", e); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java b/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java index fa506a328..4c6d424da 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java @@ -38,21 +38,22 @@ public class ReportingSet implements SortedSet { private Options duplicateOption = Options.IGNORE; private Log.Level duplicateLogLevel = Log.Level.WARN; private Log log = DefaultLog.INSTANCE; - private Function duplicateFmt = (t) -> String.format("Duplicate %s (%s) detected %s", t.getClass(), t); + private Function duplicateFmt = (t) -> String.format("Duplicate %s (%s) detected %s", t.getClass(), t); + + public enum Options { + OVERWRITE, IGNORE, FAIL + } - public enum Options { OVERWRITE, IGNORE, FAIL } - /** - * Constructor. - * Creates a TreeSet of type T. + * Constructor. Creates a TreeSet of type T. */ public ReportingSet() { this(new TreeSet()); } - + /** * Constructs. - * + * * @param delegate the SortedSet to delegate to. */ public ReportingSet(SortedSet delegate) { @@ -61,16 +62,18 @@ public ReportingSet(SortedSet delegate) { /** * Sets the function to generate the log message. - * @param msgFmt A function to return the string to be displayed when a collision occurs. + * @param msgFmt A function to return the string to be displayed when a + * collision occurs. * @return This for chaining. */ - public ReportingSet setMsgFormat(Function msgFmt) { + public ReportingSet setMsgFormat(Function msgFmt) { duplicateFmt = msgFmt; return this; } + /** - * If set true attempts to duplicate will throw an IllegalArgumentException. - * The default state is false;. + * If set true attempts to duplicate will throw an IllegalArgumentException. The + * default state is false;. * @param state the state to set. * @return this for chaining. */ @@ -80,8 +83,8 @@ public ReportingSet setDuplicateOption(Options state) { } /** - * Sets the log that the reporting set will log to. - * if not set the DefaultLog is used. + * Sets the log that the reporting set will log to. if not set the DefaultLog is + * used. * @param log the Log implementation to use. * @return this for chaining. */ @@ -91,8 +94,8 @@ public ReportingSet setLog(Log log) { } /** - * Sets the log level that the reporting set will log at. - * if not set the default level is WARN. + * Sets the log level that the reporting set will log at. if not set the default + * level is WARN. * @param level the log level to use. * @return this for chaining. */ @@ -102,35 +105,36 @@ public ReportingSet setLogLevel(Log.Level level) { } private ReportingSet sameConfig(SortedSet delegate) { - ReportingSet result = delegate instanceof ReportingSet ? (ReportingSet) delegate : new ReportingSet<>(delegate); + ReportingSet result = delegate instanceof ReportingSet ? (ReportingSet) delegate + : new ReportingSet<>(delegate); return result.setDuplicateOption(this.duplicateOption).setLog(this.log).setLogLevel(this.duplicateLogLevel); } /** - * Adds the item if it is not present. Does not report collisions. + * Adds the item if it is not present. Does not report collisions. * @param e the item to add. * @return true if the item was added, false otherwise. */ public boolean addIfNotPresent(T e) { return add(false, e); } - + @Override public boolean add(T e) { return add(true, e); } - + /** - * Attempts to add an item. Report failures if reportDup is true. + * Attempts to add an item. Report failures if reportDup is true. * @param reportDup the reporting flag. * @param e the item to add * @return true if the item was added. */ private boolean add(boolean reportDup, T e) { if (delegate.contains(e)) { - String msg = String.format("%s",ReportingSet.this.duplicateFmt.apply(e)); + String msg = String.format("%s", ReportingSet.this.duplicateFmt.apply(e)); if (reportDup) { - msg = String.format( "%s (action: %s)", msg, duplicateOption); + msg = String.format("%s (action: %s)", msg, duplicateOption); log.log(duplicateLogLevel, msg); } switch (duplicateOption) { @@ -155,7 +159,6 @@ public boolean addAll(Collection c) { return updated; } - public boolean addAllIfNotPresent(Collection c) { boolean updated = false; for (T e : c) { @@ -163,7 +166,7 @@ public boolean addAllIfNotPresent(Collection c) { } return updated; } - + @Override public void clear() { delegate.clear(); From cf09aabb530ec00787bb62bf2243ac06ca484673 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Fri, 22 Mar 2024 13:28:34 +0100 Subject: [PATCH 04/77] fixed javadoc error --- .../main/java/org/apache/rat/analysis/HeaderCheckWorker.java | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) 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 7285d95ac..a6394ea01 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 @@ -56,8 +56,7 @@ public class HeaderCheckWorker { /** * Read the input and perform the header check. * - * @throws RatHeaderAnalysisException on IO Exception. - * @throws IOException + * @throws IOException on input failure */ public static IHeaders readHeader(BufferedReader reader, int numberOfLines) throws IOException { final StringBuilder headers = new StringBuilder(); From 5a1444d8196866f9fe313a16734487c9998bd9db Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Thu, 28 Mar 2024 08:11:53 +0100 Subject: [PATCH 05/77] Cleaned up tests --- .../analysis/matchers/FullTextMatcherTest.java | 17 ++++++----------- .../rat/analysis/matchers/SPDXMatcherTest.java | 7 ++++--- .../analysis/matchers/SimpleCopyrightTests.java | 8 +++++--- .../matchers/SimpleTextMatcherTest.java | 7 ++++--- .../apache/rat/report/xml/XmlReportTest.java | 1 - 5 files changed, 19 insertions(+), 21 deletions(-) diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java index c029513ae..dbdccda58 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/FullTextMatcherTest.java @@ -18,21 +18,16 @@ */ package org.apache.rat.analysis.matchers; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; -import static org.junit.jupiter.api.Assertions.assertEquals; - -import java.util.Locale; - -import org.apache.commons.lang3.tuple.Pair; -import org.apache.rat.analysis.IHeaders; - public class FullTextMatcherTest { FullTextMatcher target = new FullTextMatcher("Hello world"); - + @BeforeEach public void setup() { target.reset(); @@ -40,8 +35,8 @@ public void setup() { @Test public void testMatch() { - assertEquals(false, target.matches(AbstractMatcherTest.makeHeaders(null, "what in the world"))); - assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders(null, "hello world"))); - assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders(null, "HELLO world"))); + assertFalse(target.matches(AbstractMatcherTest.makeHeaders(null, "what in the world"))); + assertTrue(target.matches(AbstractMatcherTest.makeHeaders(null, "hello world"))); + assertTrue(target.matches(AbstractMatcherTest.makeHeaders(null, "HELLO world"))); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java index 1145058d6..819cdc694 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SPDXMatcherTest.java @@ -18,7 +18,8 @@ */ package org.apache.rat.analysis.matchers; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.apache.rat.analysis.IHeaderMatcher; import org.junit.jupiter.api.BeforeEach; @@ -35,8 +36,8 @@ public void setup() { @Test public void testMatch() { - assertEquals(false, target.matches(AbstractMatcherTest.makeHeaders("SPDX-License-Identifier: Apache-2", null))); - assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders("SPDX-License-Identifier: hello", null))); + assertFalse(target.matches(AbstractMatcherTest.makeHeaders("SPDX-License-Identifier: Apache-2", null))); + assertTrue(target.matches(AbstractMatcherTest.makeHeaders("SPDX-License-Identifier: hello", null))); target.reset(); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java index 3da63c337..7589fb961 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleCopyrightTests.java @@ -18,7 +18,9 @@ */ package org.apache.rat.analysis.matchers; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; + import org.junit.jupiter.api.Test; public class SimpleCopyrightTests { @@ -27,8 +29,8 @@ public class SimpleCopyrightTests { @Test public void testTrueIsAlwaysTrue() { - assertEquals( true, target.matches(AbstractMatcherTest.makeHeaders("hello Copyright 1999", null))); - assertEquals( false, target.matches(AbstractMatcherTest.makeHeaders("A non matching line",null))); + assertTrue(target.matches(AbstractMatcherTest.makeHeaders("hello Copyright 1999", null))); + assertFalse(target.matches(AbstractMatcherTest.makeHeaders("A non matching line",null))); target.reset(); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java index 567e97960..9801ba4e2 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/SimpleTextMatcherTest.java @@ -18,7 +18,8 @@ */ package org.apache.rat.analysis.matchers; -import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertTrue; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -34,8 +35,8 @@ public void setup() { @Test public void testMatch() { - assertEquals(false, target.matches(AbstractMatcherTest.makeHeaders("what in the world",null))); - assertEquals(true, target.matches(AbstractMatcherTest.makeHeaders("hello world",null))); + assertFalse(target.matches(AbstractMatcherTest.makeHeaders("what in the world",null))); + assertTrue(target.matches(AbstractMatcherTest.makeHeaders("hello world",null))); target.reset(); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java index 12ccc8e11..2af06f330 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java @@ -102,7 +102,6 @@ public void baseReport() throws Exception { XPath xPath = XPathFactory.newInstance().newXPath(); Document doc = XmlUtils.toDom(new ByteArrayInputStream(out.toByteArray())); - XmlUtils.printDocument(System.out, doc); XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/ILoggerFactory.java", "QOS", null, "standard"); XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Image.png", null, null, "binary"); XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/LICENSE", null, null, "notice"); From 78d9c6dc6772579f3cb00ed8f50fbc461e65ae2d Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Thu, 28 Mar 2024 08:23:51 +0100 Subject: [PATCH 06/77] Removed format only changes --- .../rat/analysis/DefaultAnalyserFactory.java | 3 +- .../org/apache/rat/utils/ReportingSet.java | 51 +++++++++---------- .../test/java/org/apache/rat/ReportTest.java | 2 +- 3 files changed, 27 insertions(+), 29 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java index 3af84ae07..06cbe8d3a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java @@ -30,6 +30,7 @@ import org.apache.rat.document.impl.guesser.NoteGuesser; import org.apache.rat.license.ILicense; import org.apache.rat.utils.Log; +import org.apache.rat.utils.Log.Level; /** * Creates default analysers. @@ -38,7 +39,7 @@ public class DefaultAnalyserFactory { /** * Creates a DocumentAnalyser from a collection of ILicenses. - * @param licenses The licenses to use in the Analyser. + * @param licenses The licenses to use in the Analyser. * @return A document analyser that uses the provides licenses. */ public static IDocumentAnalyser createDefaultAnalyser(Log log, Collection licenses) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java b/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java index 4c6d424da..fa506a328 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/ReportingSet.java @@ -38,22 +38,21 @@ public class ReportingSet implements SortedSet { private Options duplicateOption = Options.IGNORE; private Log.Level duplicateLogLevel = Log.Level.WARN; private Log log = DefaultLog.INSTANCE; - private Function duplicateFmt = (t) -> String.format("Duplicate %s (%s) detected %s", t.getClass(), t); - - public enum Options { - OVERWRITE, IGNORE, FAIL - } + private Function duplicateFmt = (t) -> String.format("Duplicate %s (%s) detected %s", t.getClass(), t); + public enum Options { OVERWRITE, IGNORE, FAIL } + /** - * Constructor. Creates a TreeSet of type T. + * Constructor. + * Creates a TreeSet of type T. */ public ReportingSet() { this(new TreeSet()); } - + /** * Constructs. - * + * * @param delegate the SortedSet to delegate to. */ public ReportingSet(SortedSet delegate) { @@ -62,18 +61,16 @@ public ReportingSet(SortedSet delegate) { /** * Sets the function to generate the log message. - * @param msgFmt A function to return the string to be displayed when a - * collision occurs. + * @param msgFmt A function to return the string to be displayed when a collision occurs. * @return This for chaining. */ - public ReportingSet setMsgFormat(Function msgFmt) { + public ReportingSet setMsgFormat(Function msgFmt) { duplicateFmt = msgFmt; return this; } - /** - * If set true attempts to duplicate will throw an IllegalArgumentException. The - * default state is false;. + * If set true attempts to duplicate will throw an IllegalArgumentException. + * The default state is false;. * @param state the state to set. * @return this for chaining. */ @@ -83,8 +80,8 @@ public ReportingSet setDuplicateOption(Options state) { } /** - * Sets the log that the reporting set will log to. if not set the DefaultLog is - * used. + * Sets the log that the reporting set will log to. + * if not set the DefaultLog is used. * @param log the Log implementation to use. * @return this for chaining. */ @@ -94,8 +91,8 @@ public ReportingSet setLog(Log log) { } /** - * Sets the log level that the reporting set will log at. if not set the default - * level is WARN. + * Sets the log level that the reporting set will log at. + * if not set the default level is WARN. * @param level the log level to use. * @return this for chaining. */ @@ -105,36 +102,35 @@ public ReportingSet setLogLevel(Log.Level level) { } private ReportingSet sameConfig(SortedSet delegate) { - ReportingSet result = delegate instanceof ReportingSet ? (ReportingSet) delegate - : new ReportingSet<>(delegate); + ReportingSet result = delegate instanceof ReportingSet ? (ReportingSet) delegate : new ReportingSet<>(delegate); return result.setDuplicateOption(this.duplicateOption).setLog(this.log).setLogLevel(this.duplicateLogLevel); } /** - * Adds the item if it is not present. Does not report collisions. + * Adds the item if it is not present. Does not report collisions. * @param e the item to add. * @return true if the item was added, false otherwise. */ public boolean addIfNotPresent(T e) { return add(false, e); } - + @Override public boolean add(T e) { return add(true, e); } - + /** - * Attempts to add an item. Report failures if reportDup is true. + * Attempts to add an item. Report failures if reportDup is true. * @param reportDup the reporting flag. * @param e the item to add * @return true if the item was added. */ private boolean add(boolean reportDup, T e) { if (delegate.contains(e)) { - String msg = String.format("%s", ReportingSet.this.duplicateFmt.apply(e)); + String msg = String.format("%s",ReportingSet.this.duplicateFmt.apply(e)); if (reportDup) { - msg = String.format("%s (action: %s)", msg, duplicateOption); + msg = String.format( "%s (action: %s)", msg, duplicateOption); log.log(duplicateLogLevel, msg); } switch (duplicateOption) { @@ -159,6 +155,7 @@ public boolean addAll(Collection c) { return updated; } + public boolean addAllIfNotPresent(Collection c) { boolean updated = false; for (T e : c) { @@ -166,7 +163,7 @@ public boolean addAllIfNotPresent(Collection c) { } return updated; } - + @Override public void clear() { delegate.clear(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java index 0636ed77e..8632e0294 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java @@ -49,7 +49,7 @@ public void parseExclusionsForCLIUsage() { public void testDefaultConfiguration() throws ParseException, IOException { String[] empty = {}; CommandLine cl = new DefaultParser().parse(Report.buildOptions(), empty); - ReportConfiguration config = Report.createConfiguration(".", cl); + ReportConfiguration config = Report.createConfiguration("", cl); ReportConfigurationTest.validateDefault(config); } From f4cf89eff34210c9687117b2dc561046cfd437ab Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Fri, 29 Mar 2024 14:56:27 +0100 Subject: [PATCH 07/77] first passing text --- .../rat/analysis/DefaultAnalyserFactory.java | 29 +- .../rat/analysis/DocumentHeaderAnalyser.java | 21 +- .../rat/analysis/HeaderCheckWorker.java | 39 +- .../apache/rat/analysis/UnknownLicense.java | 8 +- .../java/org/apache/rat/api/Document.java | 2 + .../java/org/apache/rat/api/MetaData.java | 494 ++++++++---------- .../apache/rat/license/ILicenseFamily.java | 4 + .../org/apache/rat/policy/DefaultPolicy.java | 23 +- .../rat/report/claim/ClaimStatistic.java | 110 +--- .../claim/impl/AbstractClaimReporter.java | 57 +- .../report/claim/impl/ClaimAggregator.java | 66 ++- .../impl/xml/SimpleXmlClaimReporter.java | 97 ++-- .../claim/util/LicenseAddingReport.java | 6 +- .../rat/report/xml/writer/IXmlWriter.java | 15 +- .../xml/writer/impl/base/XmlWriter.java | 42 +- .../main/resources/org/apache/rat/default.xml | 11 +- .../resources/org/apache/rat/plain-rat.xsl | 69 +-- .../test/java/org/apache/rat/ReportTest.java | 105 +++- .../java/org/apache/rat/ReporterTest.java | 161 ++++-- .../rat/analysis/AnalyserFactoryTest.java | 26 +- .../rat/analysis/HeaderCheckWorkerTest.java | 6 +- .../analysis/license/AbstractLicenseTest.java | 39 +- .../apache/rat/policy/DefaultPolicyTest.java | 42 +- .../rat/report/xml/XmlReportFactoryTest.java | 13 +- .../apache/rat/report/xml/XmlReportTest.java | 119 ----- .../org/apache/rat/testhelpers/TextUtils.java | 17 +- .../org/apache/rat/testhelpers/XmlUtils.java | 67 ++- .../src/test/resources/elements/generated.txt | 3 + .../src/test/resources/elements/tri.txt | 6 + 29 files changed, 781 insertions(+), 916 deletions(-) delete mode 100644 apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java create mode 100644 apache-rat-core/src/test/resources/elements/generated.txt create mode 100644 apache-rat-core/src/test/resources/elements/tri.txt diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java index 06cbe8d3a..e149b78e5 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java @@ -22,7 +22,6 @@ import org.apache.rat.ConfigurationException; import org.apache.rat.api.Document; -import org.apache.rat.api.MetaData; import org.apache.rat.document.IDocumentAnalyser; import org.apache.rat.document.RatDocumentAnalysisException; import org.apache.rat.document.impl.guesser.ArchiveGuesser; @@ -30,7 +29,6 @@ import org.apache.rat.document.impl.guesser.NoteGuesser; import org.apache.rat.license.ILicense; import org.apache.rat.utils.Log; -import org.apache.rat.utils.Log.Level; /** * Creates default analysers. @@ -39,7 +37,7 @@ public class DefaultAnalyserFactory { /** * Creates a DocumentAnalyser from a collection of ILicenses. - * @param licenses The licenses to use in the Analyser. + * @param licenses The licenses to use in the Analyser. * @return A document analyser that uses the provides licenses. */ public static IDocumentAnalyser createDefaultAnalyser(Log log, Collection licenses) { @@ -48,7 +46,7 @@ public static IDocumentAnalyser createDefaultAnalyser(Log log, Collection licenses; /** The log to use */ private final Log log; @@ -67,26 +63,23 @@ private final static class DefaultAnalyser implements IDocumentAnalyser { * Constructs a DocumentAnalyser for the specified license. * @param license The license to analyse */ - public DefaultAnalyser(final Log log, final ILicense license) { - this.license = license; + public DefaultAnalyser(final Log log, final Collection licenses) { + this.licenses = licenses; this.log = log; } @Override public void analyse(Document document) throws RatDocumentAnalysisException { - final MetaData.Datum documentCategory; if (NoteGuesser.isNote(document)) { - documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_NOTICE; + document.getMetaData().setDocumentType(Document.Type.notice); } else if (ArchiveGuesser.isArchive(document)) { - documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_ARCHIVE; + document.getMetaData().setDocumentType(Document.Type.archive); } else if (BinaryGuesser.isBinary(document)) { - documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_BINARY; + document.getMetaData().setDocumentType(Document.Type.binary); } else { - documentCategory = MetaData.RAT_DOCUMENT_CATEGORY_DATUM_STANDARD; - final DocumentHeaderAnalyser headerAnalyser = new DocumentHeaderAnalyser(log, license); - headerAnalyser.analyse(document); + document.getMetaData().setDocumentType(Document.Type.standard); + new DocumentHeaderAnalyser(log, licenses).analyse(document); } - document.getMetaData().set(documentCategory); } } } 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 9534db9e7..6c0ad1824 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,6 +20,7 @@ import java.io.IOException; import java.io.Reader; +import java.util.Collection; import org.apache.rat.api.Document; import org.apache.rat.document.IDocumentAnalyser; @@ -34,10 +35,8 @@ */ class DocumentHeaderAnalyser implements IDocumentAnalyser { - /** - * The license to analyse - */ - private final ILicense license; + /** The license to analyse */ + private final Collection licenses; /** the logger to use */ private final Log log; @@ -46,22 +45,24 @@ class DocumentHeaderAnalyser implements IDocumentAnalyser { * * @param license The license to analyse */ - public DocumentHeaderAnalyser(final Log log, final ILicense license) { + public DocumentHeaderAnalyser(final Log log, final Collection licenses) { super(); - this.license = license; + this.licenses = licenses; this.log = log; } @Override - public void analyse(Document document) throws RatDocumentAnalysisException { + public void analyse(Document document) { try (Reader reader = document.reader()) { log.debug(format("Processing: %s", document)); - HeaderCheckWorker worker = new HeaderCheckWorker(reader, license, document); + HeaderCheckWorker worker = new HeaderCheckWorker(reader, licenses, document); worker.read(); } catch (IOException e) { - throw new RatDocumentAnalysisException("Cannot read header", e); + log.warn(String.format("Can not read header of %s",document)); + document.getMetaData().setDocumentType(Document.Type.unknown); } catch (RatHeaderAnalysisException e) { - throw new RatDocumentAnalysisException("Cannot analyse header", e); + log.warn(String.format("Can not process header of %s",document)); + document.getMetaData().setDocumentType(Document.Type.unknown); } } 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 a6394ea01..30d25fa54 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,6 +21,7 @@ import java.io.BufferedReader; import java.io.IOException; import java.io.Reader; +import java.util.Collection; import java.util.Locale; import java.util.Objects; @@ -29,6 +30,7 @@ import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; import org.apache.rat.license.ILicense; +import org.apache.rat.license.ILicenseFamily; /** * Reads from a stream to check license.

Note that this @@ -50,7 +52,7 @@ public class HeaderCheckWorker { private final int numberOfRetainedHeaderLines; private final BufferedReader reader; - private final ILicense license; + private final Collection licenses; private final Document document; /** @@ -94,8 +96,8 @@ public String toString() { * @param license The license to check against. not null. * @param name The document that is being checked. possibly null */ - public HeaderCheckWorker(Reader reader, final ILicense license, final Document name) { - this(reader, DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES, license, name); + public HeaderCheckWorker(Reader reader, final Collection licenses, final Document name) { + this(reader, DEFAULT_NUMBER_OF_RETAINED_HEADER_LINES, licenses, name); } /** @@ -104,20 +106,20 @@ public HeaderCheckWorker(Reader reader, final ILicense license, final Document n * @param reader The reader on the document. not null. * @param numberOfRetainedHeaderLine the maximum number of lines to read to find * the license information. - * @param license The license to check against. not null. - * @param name The document that is being checked. possibly null + * @param license The licenses to check against. not null. + * @param document The document that is being checked. possibly null */ - public HeaderCheckWorker(Reader reader, int numberOfRetainedHeaderLine, final ILicense license, - final Document name) { + public HeaderCheckWorker(Reader reader, int numberOfRetainedHeaderLine, final Collection licenses, + final Document document) { Objects.requireNonNull(reader, "Reader may not be null"); - Objects.requireNonNull(license, "License may not be null"); + Objects.requireNonNull(licenses, "Licenses may not be null"); if (numberOfRetainedHeaderLine < 0) { throw new ConfigurationException("numberOfRetainedHeaderLine may not be less than zero"); } this.reader = reader instanceof BufferedReader ? (BufferedReader) reader : new BufferedReader(reader); this.numberOfRetainedHeaderLines = numberOfRetainedHeaderLine; - this.license = license; - this.document = name; + this.licenses = licenses; + this.document = document; } /** @@ -128,15 +130,20 @@ public HeaderCheckWorker(Reader reader, int numberOfRetainedHeaderLine, final IL public void read() throws RatHeaderAnalysisException { try { final IHeaders headers = readHeader(reader, numberOfRetainedHeaderLines); - if (license.matches(headers)) { - document.getMetaData().reportOnLicense(license); - } else { - document.getMetaData().reportOnLicense(UnknownLicense.INSTANCE); - document.getMetaData().set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, headers.raw())); + licenses.stream().filter(lic -> lic.matches(headers)).forEach(document.getMetaData()::reportOnLicense); + if (document.getMetaData().detectedLicense()) { + if (document.getMetaData().licenses().anyMatch( lic -> lic.getLicenseFamily().getFamilyCategory().equals(ILicenseFamily.GENTERATED_CATEGORY))) { + document.getMetaData().setDocumentType(Document.Type.generated); + } } + else { + document.getMetaData().reportOnLicense(UnknownLicense.INSTANCE); + document.getMetaData().setSampleHeader(headers.raw()); + } } catch (IOException e) { throw new RatHeaderAnalysisException("Cannot read header for " + document, e); + } finally { + licenses.forEach(ILicense::reset); } - license.reset(); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java index 881ab4676..a7edf752a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java @@ -33,21 +33,21 @@ public class UnknownLicense implements ILicense { /** * The single instance of this class. */ - static final UnknownLicense INSTANCE = new UnknownLicense(); + public static final UnknownLicense INSTANCE = new UnknownLicense(); private final ILicenseFamily family ; /** * Do not allow other constructions. */ - UnknownLicense() { - family = new ILicenseFamilyBuilder().setLicenseFamilyCategory("?????") + private UnknownLicense() { + family = new ILicenseFamilyBuilder().setLicenseFamilyCategory(ILicenseFamily.UNKNOWN_CATEGORY) .setLicenseFamilyName("Unknown license").build(); } @Override public String getId() { - return "?????"; + return ILicenseFamily.UNKNOWN_CATEGORY; } @Override diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java index 9cf8d1413..0f99c4a4b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java +++ b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java @@ -25,6 +25,8 @@ import org.apache.rat.document.CompositeDocumentException; public interface Document { + + enum Type {generated, unknown, archive, notice, binary, standard}; /** * @return the name of the current document. diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java index 201f7f783..47b5b4921 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java +++ b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java @@ -23,155 +23,66 @@ import java.util.Collections; import java.util.Iterator; import java.util.List; +import java.util.Objects; +import java.util.Set; +import java.util.HashSet; +import java.util.TreeSet; +import java.util.SortedSet; +import java.util.stream.Stream; import org.apache.commons.lang3.StringUtils; +import org.apache.rat.analysis.UnknownLicense; import org.apache.rat.license.ILicense; +import org.apache.rat.license.ILicenseFamily; /** * Data about the document under test.. */ public class MetaData { + + public static final String RAT_BASE_URL = "http://org/apache/rat/meta-data"; // Document Categories public static final String RAT_URL_DOCUMENT_CATEGORY = RAT_BASE_URL + "#FileCategory"; - public static final String RAT_DOCUMENT_CATEGORY_VALUE_GENERATED = "GEN "; - public static final String RAT_DOCUMENT_CATEGORY_VALUE_UNKNOWN = "?????"; - public static final String RAT_DOCUMENT_CATEGORY_VALUE_ARCHIVE = "archive"; - public static final String RAT_DOCUMENT_CATEGORY_VALUE_NOTICE = "notice"; - public static final String RAT_DOCUMENT_CATEGORY_VALUE_BINARY = "binary"; - public static final String RAT_DOCUMENT_CATEGORY_VALUE_STANDARD = "standard"; - public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_GENERATED = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_GENERATED); - public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_UNKNOWN = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_UNKNOWN); - public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_ARCHIVE = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_ARCHIVE); - public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_NOTICE = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_NOTICE); - public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_BINARY = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_BINARY); - public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_STANDARD = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_STANDARD); +// public static final String RAT_DOCUMENT_CATEGORY_VALUE_GENERATED = "GEN "; +// public static final String RAT_DOCUMENT_CATEGORY_VALUE_UNKNOWN = "?????"; +// public static final String RAT_DOCUMENT_CATEGORY_VALUE_ARCHIVE = "archive"; +// public static final String RAT_DOCUMENT_CATEGORY_VALUE_NOTICE = "notice"; +// public static final String RAT_DOCUMENT_CATEGORY_VALUE_BINARY = "binary"; +// public static final String RAT_DOCUMENT_CATEGORY_VALUE_STANDARD = "standard"; +// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_GENERATED = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_GENERATED); +// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_UNKNOWN = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_UNKNOWN); +// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_ARCHIVE = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_ARCHIVE); +// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_NOTICE = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_NOTICE); +// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_BINARY = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_BINARY); +// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_STANDARD = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_STANDARD); // Header Categories - public static final String RAT_URL_HEADER_CATEGORY = RAT_BASE_URL + "#HeaderCategory"; + //public static final String RAT_URL_HEADER_CATEGORY = RAT_BASE_URL + "#HeaderCategory"; // License Family Categories - public static final String RAT_URL_LICENSE_FAMILY_CATEGORY= RAT_BASE_URL + "#LicenseFamilyCategory"; + //public static final String RAT_URL_LICENSE_FAMILY_CATEGORY= RAT_BASE_URL + "#LicenseFamilyCategory"; // Shortcuts used in report output, must be exactly 5 characters - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN = "GEN "; - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN = "?????"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_ASL = "AL "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_OASIS = "OASIS"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3CD = "W3CD "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3C = "W3C "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_DOJO = "DOJO "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_TMF = "TMF "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL1 ="GPL1 "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL2 ="GPL2 "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL3 = "GPL3 "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_MIT = "MIT "; - @Deprecated - public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_CDDL1 = "CDDL1"; + // public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN = "GEN "; + //public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN = "?????"; + + + //public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GEN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN); + //public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_UNKNOWN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN); - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GEN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN); - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_UNKNOWN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_ASL = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_ASL); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_OASIS = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_OASIS); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_W3CD = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3CD); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_W3C = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_W3C); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_DOJO = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_DOJO); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_TMF = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_TMF); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL1 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL1); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL2 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL2); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GPL3 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_GPL3); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_MIT = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_MIT); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_CDLL1 = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY,RAT_LICENSE_FAMILY_CATEGORY_VALUE_CDDL1); // License Family Standard Names - public static final String RAT_URL_LICENSE_FAMILY_NAME= RAT_BASE_URL + "#LicenseFamilyName"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_W3C_SOFTWARE_COPYRIGHT = "W3C Software Copyright"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_W3C_DOCUMENT_COPYRIGHT = "W3C Document Copyright"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_OASIS_OPEN_LICENSE = "OASIS Open License"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_MODIFIED_BSD_LICENSE = "Modified BSD License"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_APACHE_LICENSE_VERSION_2_0 = "Apache License Version 2.0"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_1 = - "GNU General Public License, version 1"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_2 = - "GNU General Public License, version 2"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_3 = - "GNU General Public License, version 3"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_MIT = - "The MIT License"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_CDDL1 = - "COMMON DEVELOPMENT AND DISTRIBUTION LICENSE Version 1.0"; - @Deprecated - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_ACADEMIC_FREE_LICENSE_VERSION_2_1 = "Academic Free License, Version 2.1"; + // public static final String RAT_URL_LICENSE_FAMILY_NAME= RAT_BASE_URL + "#LicenseFamilyName"; + + - public static final String RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN = "?????"; - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_W3C_SOFTWARE_COPYRIGHT - = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_W3C_SOFTWARE_COPYRIGHT); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_W3C_DOCUMENT_COPYRIGHT - = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_W3C_DOCUMENT_COPYRIGHT); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_OASIS_OPEN_LICENSE - = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_OASIS_OPEN_LICENSE); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_MODIFIED_BSD_LICENSE - = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_MODIFIED_BSD_LICENSE); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_APACHE_LICENSE_VERSION_2_0 - = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_APACHE_LICENSE_VERSION_2_0); - @Deprecated - public static final Datum - RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_1 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_1); - @Deprecated - public static final Datum - RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_2 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_2); - @Deprecated - public static final Datum - RAT_LICENSE_FAMILY_NAME_DATUM_GPL_VERSION_3 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_GPL_VERSION_3); - @Deprecated - public static final Datum - RAT_LICENSE_FAMILY_NAME_DATUM_MIT = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_MIT); - @Deprecated - public static final Datum - RAT_LICENSE_FAMILY_NAME_DATUM_CDDL1 = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_CDDL1); - @Deprecated - public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_ACADEMIC_FREE_LICENSE_VERSION_2_1 - = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_ACADEMIC_FREE_LICENSE_VERSION_2_1); + //public static final String RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN = "?????"; + - public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_UNKNOWN - = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN); + //public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_UNKNOWN + // = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN); // Header sample public static final String RAT_URL_HEADER_SAMPLE = RAT_BASE_URL + "#HeaderSample"; @@ -180,178 +91,223 @@ public class MetaData { public static final String RAT_URL_APPROVED_LICENSE = RAT_BASE_URL + "#ApprovedLicense"; public static final String RAT_APPROVED_LICENSE_VALUE_TRUE = Boolean.TRUE.toString(); public static final String RAT_APPROVED_LICENSE_VALUE_FALSE = Boolean.FALSE.toString(); - public static final Datum RAT_APPROVED_LICENSE_DATUM_TRUE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_TRUE); - public static final Datum RAT_APPROVED_LICENSE_DATUM_FALSE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_FALSE); - @Deprecated - public static final Datum RAT_APPROVED_LICENSE_DATIM_TRUE = RAT_APPROVED_LICENSE_DATUM_TRUE; - @Deprecated - public static final Datum RAT_APPROVED_LICENSE_DATIM_FALSE = RAT_APPROVED_LICENSE_DATUM_FALSE; +// public static final Datum RAT_APPROVED_LICENSE_DATUM_TRUE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_TRUE); +// public static final Datum RAT_APPROVED_LICENSE_DATUM_FALSE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_FALSE); + /** * Only likely to be a small quantity of data * so trade some performance for simplicity. */ - private final List data; - + // private final List data; + /** The list of matched licenses */ + private final SortedSet matchedLicenses; + private final Set approvedLicenses; + + private Document.Type documentType; + private String sampleHeader; /** * Create metadata without a content type. */ public MetaData() { - this.data = new ArrayList<>(16); + this.matchedLicenses = new TreeSet<>(); + this.approvedLicenses = new HashSet<>(); + // this.data = new ArrayList<>(16); } - /** - * Add the license information to the metadata. - * @param license the license to add metadata for. - */ - public void reportOnLicense(ILicense license) { - - if (StringUtils.isNotBlank(license.getNotes())) { - set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, license.getNotes())); - } - set(new MetaData.Datum(MetaData.RAT_URL_HEADER_CATEGORY, license.getLicenseFamily().getFamilyCategory())); - set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY, license.getLicenseFamily().getFamilyCategory())); - set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_NAME, license.getLicenseFamily().getFamilyName())); + public boolean detectedLicense() { + return !matchedLicenses.isEmpty(); } - - /** - * Gets all data. - * @return unmodifiable view of the meta data. - */ - public Collection getData() { - return Collections.unmodifiableCollection(data); + public void setApprovedLicenses(Set approvedLicenseFamilies) { + licenses().filter( lic -> approvedLicenseFamilies.contains(lic.getLicenseFamily())).forEach(lic -> approvedLicenses.add(lic.getId())); } - /** - * Adds a new datum. - * Existing data with the same name are not replaced. - * @param datum datum to add. - * @see #set(org.apache.rat.api.MetaData.Datum) - */ - public void add(final Datum datum) { - data.add(datum); + public Stream licenses() { + return matchedLicenses.stream(); } - /** - * Puts in a new datum replacing any existing data. - * Any current data matching the name are removed. - * @param datum not null - * @see #add(org.apache.rat.api.MetaData.Datum) - */ - public void set(final Datum datum) { - clear(datum.getName()); - add(datum); + public Stream approvedLicenses() { + return licenses().filter(this::isApproved); } - /** - * Gets the first datum matching the given name. - * @param name not null - * @return the matching datum first added when there is any matching data, - * null otherwise - */ - public Datum get(final String name) { - Datum result = null; - for (Datum next : data) { - if (name.equals(next.getName())) { - result = next; - break; - } - } - return result; + public boolean isApproved(ILicense license) { + return approvedLicenses.contains(license.getId()); } - /** - * Gets the value of the first datum matching the given name. - * @param name not null - * @return the value of the matchin datum first added when there is any matching data, - * null otherwise - */ - public String value(final String name) { - final Datum datum = get(name); - final String result; - if (datum == null) { - result = null; - } else { - result = datum.getValue(); - } - return result; + public Stream unapprovedLicenses() { + return licenses().filter( lic -> !isApproved(lic)); + } + + public void setSampleHeader(String sampleHeader) { + this.sampleHeader = sampleHeader; } - /** - * Removes all data matching the given name. - * @param name not null - * @return true if any data match, false otherwise - */ - public boolean clear(final String name) { - boolean dataRemoved = false; - for (final Iterator it = data.iterator();it.hasNext();) { - final Datum datum = it.next(); - if (datum.getName().equals(name)) { - it.remove(); - dataRemoved = true; - } - } - return dataRemoved; + public String getSampleHeader() { + return sampleHeader; } - /** - * Clears all data. - */ - public void clear() { - data.clear(); + public void setDocumentType(Document.Type type) { + this.documentType = type; + } + + public Document.Type getDocumentType() { + return this.documentType; } /** - * A datum. + * Add the license information to the metadata. + * @param license the license to add metadata for. */ - public static final class Datum { - private final String name; - private final String value; - - /** - * Constructs a datum. - * @param name not null - * @param value not null - */ - public Datum(final String name, final String value) { - super(); - this.name = name; - this.value = value; - } - - /** - * Gets the name of the data type. - * To avoid collisions, it is recommended that URLs are used. - * @return not null - */ - public String getName() { - return name; - } - - /** - * Data type value. - * @return not null - */ - public String getValue() { - return value; - } - - /** - * Constructs a String with all attributes - * in name = value format. - * - * @return a String representation - * of this object. - */ - @Override - public String toString() - { - return "Datum [ " - + "name ='" + this.name + "'," - + "value ='" + this.value + " " - + "']"; - } + public void reportOnLicense(ILicense license) { + this.matchedLicenses.add(license); } +// if (StringUtils.isNotBlank(license.getNotes())) { +// set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, license.getNotes())); +// } +// set(new MetaData.Datum(MetaData.RAT_URL_HEADER_CATEGORY, license.getLicenseFamily().getFamilyCategory())); +// set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY, license.getLicenseFamily().getFamilyCategory())); +// set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_NAME, license.getLicenseFamily().getFamilyName())); + + + +// /** +// * Gets all data. +// * @return unmodifiable view of the meta data. +// */ +// public Collection getData() { +// return Collections.unmodifiableCollection(data); +// } +// +// /** +// * Adds a new datum. +// * Existing data with the same name are not replaced. +// * @param datum datum to add. +// * @see #set(org.apache.rat.api.MetaData.Datum) +// */ +// public void add(final Datum datum) { +// data.add(datum); +// } +// +// /** +// * Puts in a new datum replacing any existing data. +// * Any current data matching the name are removed. +// * @param datum not null +// * @see #add(org.apache.rat.api.MetaData.Datum) +// */ +// public void set(final Datum datum) { +// clear(datum.getName()); +// add(datum); +// } +// +// /** +// * Gets the first datum matching the given name. +// * @param name not null +// * @return the matching datum first added when there is any matching data, +// * null otherwise +// */ +// public Datum get(final String name) { +// Datum result = null; +// for (Datum next : data) { +// if (name.equals(next.getName())) { +// result = next; +// break; +// } +// } +// return result; +// } +// +// /** +// * Gets the value of the first datum matching the given name. +// * @param name not null +// * @return the value of the matchin datum first added when there is any matching data, +// * null otherwise +// */ +// public String value(final String name) { +// final Datum datum = get(name); +// final String result; +// if (datum == null) { +// result = null; +// } else { +// result = datum.getValue(); +// } +// return result; +// } +// +// /** +// * Removes all data matching the given name. +// * @param name not null +// * @return true if any data match, false otherwise +// */ +// public boolean clear(final String name) { +// boolean dataRemoved = false; +// for (final Iterator it = data.iterator();it.hasNext();) { +// final Datum datum = it.next(); +// if (datum.getName().equals(name)) { +// it.remove(); +// dataRemoved = true; +// } +// } +// return dataRemoved; +// } +// +// /** +// * Clears all data. +// */ +// public void clear() { +// data.clear(); +// } +// +// /** +// * A datum. +// */ +// public static final class Datum { +// private final String name; +// private final String value; +// +// /** +// * Constructs a datum. +// * @param name not null +// * @param value not null +// */ +// public Datum(final String name, final String value) { +// super(); +// this.name = name; +// this.value = value; +// } +// +// /** +// * Gets the name of the data type. +// * To avoid collisions, it is recommended that URLs are used. +// * @return not null +// */ +// public String getName() { +// return name; +// } +// +// /** +// * Data type value. +// * @return not null +// */ +// public String getValue() { +// return value; +// } +// +// /** +// * Constructs a String with all attributes +// * in name = value format. +// * +// * @return a String representation +// * of this object. +// */ +// @Override +// public String toString() +// { +// return "Datum [ " +// + "name ='" + this.name + "'," +// + "value ='" + this.value + " " +// + "']"; +// } +// } } \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java index 501a59e89..762a25b74 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicenseFamily.java @@ -22,6 +22,10 @@ * The definition of the license family. */ public interface ILicenseFamily extends Comparable { + + static final String GENTERATED_CATEGORY = "GEN "; + static final String UNKNOWN_CATEGORY = "?????"; + /** * @return the license family name. */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java b/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java index bec67c468..b8dbce554 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java +++ b/apache-rat-core/src/main/java/org/apache/rat/policy/DefaultPolicy.java @@ -54,34 +54,15 @@ public void add(ILicenseFamily approvedLicense) { @Override public void analyse(final Document document) { if (document != null) { - boolean approval; - if (document.getMetaData().value(MetaData.RAT_URL_HEADER_CATEGORY) != null) { - ILicenseFamily licenseFamily = ILicenseFamily.builder() - .setLicenseFamilyCategory( - document.getMetaData().value(MetaData.RAT_URL_HEADER_CATEGORY)) - .setLicenseFamilyName(document.getMetaData().value(MetaData.RAT_URL_LICENSE_FAMILY_NAME)) - .build(); - approval = approvedLicenseFamilies.contains(licenseFamily); - reportLicenseApprovalClaim(document, approval); - } + document.getMetaData().setApprovedLicenses(getApprovedLicenseFamilies()); } } - /** - * Report if the document as either having approved license or not. - * @param document the document to approve. - * @param isAcceptable {@code true} if the license is an approved one, {@code false} otherwise. - */ - public void reportLicenseApprovalClaim(final Document document, final boolean isAcceptable) { - document.getMetaData().set( - isAcceptable ? MetaData.RAT_APPROVED_LICENSE_DATUM_TRUE : MetaData.RAT_APPROVED_LICENSE_DATUM_FALSE); - } - /** * Gets an unmodifiable reference to the SortedSet of approved licenses that this policy is holding. * @return sorted set of license family definitions. */ - public SortedSet getApprovedLicenseNames() { + public SortedSet getApprovedLicenseFamilies() { return Collections.unmodifiableSortedSet(approvedLicenseFamilies); } } 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 578e8f673..80630bdea 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,100 +19,51 @@ package org.apache.rat.report.claim; +import java.util.HashMap; import java.util.Map; +import org.apache.rat.api.Document; + /** * This class provides a numerical overview about * the report. */ public class ClaimStatistic { - private Map documentCategoryMap, licenseFamilyCodeMap, licenseFamilyNameMap; - private int numApproved, numUnApproved, numGenerated, numUnknown; - - /** - * @return Returns the number of files with approved licenses. - */ - public int getNumApproved() { - return numApproved; - } - - /** - * Sets the number of files with approved licenses. - * @param pNumApproved number of files with approved licenses. - */ - public void setNumApproved(int pNumApproved) { - numApproved = pNumApproved; - } - - /** - * @return Returns the number of files with unapproved licenses. - * Note: This might include files with unknown - * licenses. - * @see #getNumUnknown() - */ - public int getNumUnApproved() { - return numUnApproved; - } - - /** - * Sets the number of files with unapproved licenses. - * @param pNumUnApproved number of files with unapproved licenses. - */ - public void setNumUnApproved(int pNumUnApproved) { - numUnApproved = pNumUnApproved; - } - - /** - * @return Returns the number of generated files. - */ - public int getNumGenerated() { - return numGenerated; - } + public enum Counter { Approved, Unapproved, Generated, Unknown }; + + private final Map licenseFamilyNameMap = new HashMap<>(); + private final Map licenseFamilyCodeMap = new HashMap<>(); + private final Map documentCategoryMap = new HashMap<>(); + private final Map counterMap = new HashMap<>(); - /** - * Sets the number of generated files. - * @param pNumGenerated the number of generated files. - */ - public void setNumGenerated(int pNumGenerated) { - numGenerated = pNumGenerated; - } /** - * @return Returns the number of files, which are neither - * generated nor have a known license header. - */ - public int getNumUnknown() { - return numUnknown; - } - - /** - * Sets the number of files, which are neither - * generated nor have a known license header. - * @param pNumUnknown set number of files. + * @return Returns the number of files with approved licenses. */ - public void setNumUnknown(int pNumUnknown) { - numUnknown = pNumUnknown; + public int getCounter(Counter counter) { + int[] count = counterMap.get(counter); + return count == null ? null : count[0]; } /** - * Sets a map with the file types. The map keys + * @return Returns a map with the file types. The map keys * are file type names and the map values * are integers with the number of resources matching * the file type. - * @param pDocumentCategoryMap doc-category map. */ - public void setDocumentCategoryMap(Map pDocumentCategoryMap) { - documentCategoryMap = pDocumentCategoryMap; + public Map getCounterMap() { + return counterMap; } + /** * @return Returns a map with the file types. The map keys * are file type names and the map values * are integers with the number of resources matching * the file type. */ - public Map getDocumentCategoryMap() { + public Map getDocumentCategoryMap() { return documentCategoryMap; } @@ -122,39 +73,18 @@ public Map getDocumentCategoryMap() { * the map values are integers with the number of resources * matching the license family code. */ - public Map getLicenseFileCodeMap() { + public Map getLicenseFamilyCodeMap() { return licenseFamilyCodeMap; } - /** - * Sets a map with the license family codes. The map - * keys are instances of license family category names and - * the map values are integers with the number of resources - * matching the license family code. - * @param pLicenseFamilyCodeMap license family map. - */ - public void setLicenseFileCodeMap(Map pLicenseFamilyCodeMap) { - licenseFamilyCodeMap = pLicenseFamilyCodeMap; - } - /** * @return Returns a map with the license family codes. The map * keys are the names of the license families and * the map values are integers with the number of resources * matching the license family name. */ - public Map getLicenseFileNameMap() { + public Map getLicenseFileNameMap() { return licenseFamilyNameMap; } - /** - * Sets map with the license family codes. The map - * keys are the name of the license families and - * the map values are integers with the number of resources - * matching the license family name. - * @param pLicenseFamilyNameMap license family-name map. - */ - public void setLicenseFileNameMap(Map pLicenseFamilyNameMap) { - licenseFamilyNameMap = pLicenseFamilyNameMap; - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java index ee059b649..064b8560b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/AbstractClaimReporter.java @@ -19,9 +19,12 @@ package org.apache.rat.report.claim.impl; +import java.util.stream.Collectors; + import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; import org.apache.rat.api.RatException; +import org.apache.rat.license.ILicense; import org.apache.rat.report.AbstractReport; @@ -35,7 +38,7 @@ public abstract class AbstractClaimReporter extends AbstractReport { * Empty default implementation. * @param documentCategoryName name of the category */ - protected void handleDocumentCategoryClaim(String documentCategoryName) { + protected void handleDocumentCategoryClaim(Document.Type type) { // Does nothing } @@ -43,7 +46,7 @@ protected void handleDocumentCategoryClaim(String documentCategoryName) { * Empty default implementation. * @param licenseApproved name of the approved license */ - protected void handleApprovedLicenseClaim(String licenseApproved) { + protected void handleApprovedLicenseClaim(MetaData metadata) { // Does nothing } @@ -59,58 +62,18 @@ protected void handleLicenseFamilyNameClaim(String licenseFamilyName) { * Empty default implementation. * @param headerCategory name of the header category */ - protected void handleHeaderCategoryClaim(String headerCategory) { + protected void handleHeaderCategoryClaim(ILicense license) { // Does nothing } private void writeDocumentClaim(Document subject) { final MetaData metaData = subject.getMetaData(); - writeHeaderCategory(metaData); - writeLicenseFamilyName(metaData); - writeDocumentCategory(metaData); - writeApprovedLicenseClaim(metaData); - } - - private void writeApprovedLicenseClaim(final MetaData metaData) { - final MetaData.Datum approvedLicenseDatum = metaData.get(MetaData.RAT_URL_APPROVED_LICENSE); - if (approvedLicenseDatum != null) { - final String approvedLicense = approvedLicenseDatum.getValue(); - if (approvedLicense != null) { - handleApprovedLicenseClaim(approvedLicense); - } - } + metaData.licenses().forEach(this::handleHeaderCategoryClaim); + metaData.licenses().map(lic -> lic.getLicenseFamily().getFamilyName()).collect(Collectors.toSet()).forEach(this::handleLicenseFamilyNameClaim); + handleDocumentCategoryClaim(metaData.getDocumentType()); + handleApprovedLicenseClaim(metaData); } - private void writeHeaderCategory(final MetaData metaData) { - final MetaData.Datum headerCategoryDatum = metaData.get(MetaData.RAT_URL_HEADER_CATEGORY); - if (headerCategoryDatum != null) { - final String headerCategory = headerCategoryDatum.getValue(); - if (headerCategory != null) { - handleHeaderCategoryClaim(headerCategory); - } - } - } - - private void writeLicenseFamilyName(final MetaData metaData) { - final MetaData.Datum licenseFamilyNameDatum = metaData.get(MetaData.RAT_URL_LICENSE_FAMILY_NAME); - if (licenseFamilyNameDatum != null) { - final String licenseFamilyName = licenseFamilyNameDatum.getValue(); - if (licenseFamilyName != null) { - handleLicenseFamilyNameClaim(licenseFamilyName); - } - } - } - - private void writeDocumentCategory(final MetaData metaData) { - final MetaData.Datum documentCategoryDatum = metaData.get(MetaData.RAT_URL_DOCUMENT_CATEGORY); - if (documentCategoryDatum != null) { - final String documentCategory = documentCategoryDatum.getValue(); - if (documentCategory != null) { - handleDocumentCategoryClaim(documentCategory); - } - } - } - @Override public void report(Document subject) throws RatException { writeDocumentClaim(subject); diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/ClaimAggregator.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/ClaimAggregator.java index cef444589..baca6519a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/ClaimAggregator.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/ClaimAggregator.java @@ -19,9 +19,13 @@ package org.apache.rat.report.claim.impl; +import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; import org.apache.rat.api.RatException; +import org.apache.rat.license.ILicense; +import org.apache.rat.license.ILicenseFamily; import org.apache.rat.report.claim.ClaimStatistic; +import org.apache.rat.report.claim.ClaimStatistic.Counter; import java.util.HashMap; import java.util.Map; @@ -33,70 +37,60 @@ */ public class ClaimAggregator extends AbstractClaimReporter { private final ClaimStatistic statistic; - private final Map numsByLicenseFamilyName = new HashMap<>(); - private final Map numsByLicenseFamilyCode = new HashMap<>(); - private final Map numsByFileType = new HashMap<>(); - private int numApproved, numUnApproved, numGenerated, numUnknown; public ClaimAggregator(ClaimStatistic pStatistic) { statistic = pStatistic; } - private void incMapValue(Map pMap, String pKey) { - final Integer num = pMap.get(pKey); - final int newNum; + private void incMapValue(Map map, T key, int value) { + final int[] num = map.get(key); + if (num == null) { - newNum = 1; + map.put(key,new int[] {value}); } else { - newNum = num + 1; + num[0]+= value; } - pMap.put(pKey, newNum); } @Override - protected void handleDocumentCategoryClaim(String documentCategoryName) { - incMapValue(numsByFileType, documentCategoryName); + protected void handleDocumentCategoryClaim(Document.Type documentType) { + incMapValue(statistic.getDocumentCategoryMap(), documentType, 1); } @Override - protected void handleApprovedLicenseClaim(String licenseApproved) { - if (MetaData.RAT_APPROVED_LICENSE_VALUE_TRUE.equals(licenseApproved)) { - numApproved++; + protected void handleApprovedLicenseClaim(MetaData metadata) { + incValueMap( statistic.getCounterMap(), ClaimStatistic.Counter.Approved, metadata.approvedLicenses().count()); + incValueMap( statistic.getCounterMap(), ClaimStatistic.Counter.Unapproved, metadata.unapprovedLicenses().count()); + } + + private void incValueMap(Map map, Counter key, long value) { + final int[] num = map.get(key); + + if (num == null) { + map.put(key,new int[] {(int)value}); } else { - numUnApproved++; + num[0]+= value; } } @Override protected void handleLicenseFamilyNameClaim(String licenseFamilyName) { - incMapValue(numsByLicenseFamilyName, licenseFamilyName); + incMapValue(statistic.getLicenseFileNameMap(), licenseFamilyName, 1); } @Override - protected void handleHeaderCategoryClaim(String headerCategory) { - - if (MetaData.RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN.equals(headerCategory)) { - numGenerated++; - incMapValue(numsByLicenseFamilyCode, MetaData.RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN); - } else if (MetaData.RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN.equals(headerCategory)) { - numUnknown++; - incMapValue(numsByLicenseFamilyCode, MetaData.RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN); + protected void handleHeaderCategoryClaim(ILicense license) { + String category = license.getLicenseFamily().getFamilyCategory(); + if (category.equals(ILicenseFamily.GENTERATED_CATEGORY)) { + incValueMap( statistic.getCounterMap(), Counter.Generated, 1); + } else if (category.equals(ILicenseFamily.UNKNOWN_CATEGORY)) { + incValueMap( statistic.getCounterMap(), Counter.Unknown, 1); } - } - - public void fillClaimStatistic(ClaimStatistic pStatistic) { - pStatistic.setDocumentCategoryMap(numsByFileType); - pStatistic.setLicenseFileCodeMap(numsByLicenseFamilyCode); - pStatistic.setLicenseFileNameMap(numsByLicenseFamilyName); - pStatistic.setNumApproved(numApproved); - pStatistic.setNumGenerated(numGenerated); - pStatistic.setNumUnApproved(numUnApproved); - pStatistic.setNumUnknown(numUnknown); + incMapValue(statistic.getLicenseFamilyCodeMap(), category, 1); } @Override public void endReport() throws RatException { super.endReport(); - fillClaimStatistic(statistic); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java index 085a8ccc9..dde1ba5a3 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java @@ -20,104 +20,71 @@ import java.io.IOException; import java.util.Calendar; +import java.util.Iterator; +import java.util.Optional; +import org.apache.commons.lang3.StringUtils; import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; import org.apache.rat.api.RatException; +import org.apache.rat.license.ILicense; import org.apache.rat.report.AbstractReport; import org.apache.rat.report.xml.writer.IXmlWriter; public class SimpleXmlClaimReporter extends AbstractReport { private static final String RAT_REPORT = "rat-report"; private static final String TIMESTAMP = "timestamp"; - private static final String LICENSE_APPROVAL_PREDICATE = "license-approval"; - private static final String LICENSE_FAMILY_PREDICATE = "license-family"; - private static final String HEADER_SAMPLE_PREDICATE = "header-sample"; - private static final String HEADER_TYPE_PREDICATE = "header-type"; - private static final String FILE_TYPE_PREDICATE = "type"; - + private static final String RESOURCE = "resource"; + private static final String LICENSE = "license"; + private static final String APPROVAL = "approval"; + private static final String FAMILY = "family"; + private static final String NOTES = "notes"; + private static final String SAMPLE = "sample"; + private static final String TYPE = "type"; + private static final String ID = "id"; + private final IXmlWriter writer; private static final String NAME = "name"; - private boolean firstTime = true; public SimpleXmlClaimReporter(final IXmlWriter writer) { this.writer = writer; } - /** - * Writes a single claim to the XML file. - * @param pPredicate The claims predicate. - * @param pObject The claims object. - * @param pLiteral Whether to write the object as an element (true), or an - * attribute (false). - * @throws IOException An I/O error occurred while writing the claim. - * @throws RatException Another error occurred while writing the claim. - */ - protected void writeClaim(String pPredicate, String pObject, boolean pLiteral) throws IOException, RatException { - if (pLiteral) { - writer.openElement(pPredicate).content(pObject).closeElement(); - } else { - writer.openElement(pPredicate).attribute(NAME, pObject).closeElement(); - } - } - @Override public void report(final Document subject) throws RatException { try { - if (firstTime) { - firstTime = false; - } else { - writer.closeElement(); - } - writer.openElement("resource").attribute(NAME, subject.getName()); writeDocumentClaims(subject); } catch (IOException e) { throw new RatException("XML writing failure: " + e.getMessage() + " subject: " + subject, e); } } - private void writeDocumentClaims(final Document subject) throws IOException, RatException { - final MetaData metaData = subject.getMetaData(); - writeHeaderSample(metaData); - writeHeaderCategory(metaData); - writeLicenseFamilyName(metaData); - writeApprovedLicense(metaData); - writeDocumentCategory(metaData); - } - - private void writeApprovedLicense(final MetaData metaData) throws IOException, RatException { - final String approvedLicense = metaData.value(MetaData.RAT_URL_APPROVED_LICENSE); - if (approvedLicense != null) { - writeClaim(LICENSE_APPROVAL_PREDICATE, approvedLicense, false); + private void writeLicenseClaims(ILicense license, MetaData metaData) throws IOException { + writer.openElement(LICENSE).attribute(ID, license.getId()) + .attribute(NAME, license.getName()) + .attribute(APPROVAL, Boolean.valueOf(metaData.isApproved(license)).toString()) + .attribute(FAMILY, license.getLicenseFamily().getFamilyCategory()); + if (StringUtils.isNotBlank(license.getNotes())) { + writer.openElement(NOTES).cdata(license.getNotes()).closeElement(); } + writer.closeElement(); } - - private void writeLicenseFamilyName(final MetaData metaData) throws IOException, RatException { - final String licenseFamilyName = metaData.value(MetaData.RAT_URL_LICENSE_FAMILY_NAME); - if (licenseFamilyName != null) { - writeClaim(LICENSE_FAMILY_PREDICATE, licenseFamilyName, false); - } - } - - private void writeHeaderCategory(final MetaData metaData) throws IOException, RatException { - final String headerCategory = metaData.value(MetaData.RAT_URL_HEADER_CATEGORY); - if (headerCategory != null) { - writeClaim(HEADER_TYPE_PREDICATE, headerCategory, false); + + private void writeDocumentClaims(final Document subject) throws IOException, RatException { + final MetaData metaData = subject.getMetaData(); + writer.openElement(RESOURCE).attribute(NAME, subject.getName()).attribute(TYPE, metaData.getDocumentType().toString()); + for (Iterator iter = metaData.licenses().iterator(); iter.hasNext() ;) { + writeLicenseClaims(iter.next(), metaData); } + writeHeaderSample(metaData); + writer.closeElement(); } private void writeHeaderSample(final MetaData metaData) throws IOException, RatException { - final String sample = metaData.value(MetaData.RAT_URL_HEADER_SAMPLE); - if (sample != null) { - writeClaim(HEADER_SAMPLE_PREDICATE, sample, true); - } - } - - private void writeDocumentCategory(final MetaData metaData) throws IOException, RatException { - final String documentCategory = metaData.value(MetaData.RAT_URL_DOCUMENT_CATEGORY); - if (documentCategory != null) { - writeClaim(FILE_TYPE_PREDICATE, documentCategory, false); + final String sample = metaData.getSampleHeader(); + if (StringUtils.isNotBlank(sample)) { + writer.openElement(SAMPLE).cdata(sample).closeElement(); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java index eb0dd83e6..bd64de0a4 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/LicenseAddingReport.java @@ -21,10 +21,10 @@ import java.io.File; import java.io.IOException; +import org.apache.rat.analysis.UnknownLicense; import org.apache.rat.annotation.AbstractLicenseAppender; import org.apache.rat.annotation.ApacheV2LicenseAppender; import org.apache.rat.api.MetaData; -import org.apache.rat.api.MetaData.Datum; import org.apache.rat.api.RatException; import org.apache.rat.report.AbstractReport; import org.apache.rat.utils.Log; @@ -40,9 +40,7 @@ public LicenseAddingReport(final Log log, String pCopyrightMsg, boolean pForced) @Override public void report(org.apache.rat.api.Document document) throws RatException { - final Datum licenseHeader = document.getMetaData().get(MetaData.RAT_URL_HEADER_CATEGORY); - if (licenseHeader == null - || MetaData.RAT_LICENSE_FAMILY_CATEGORY_DATUM_UNKNOWN.getValue().equals(licenseHeader.getValue())) { + if (document.getMetaData().licenses().anyMatch(lic -> lic.equals(UnknownLicense.INSTANCE))) { final File file = new File(document.getName()); if (file.isFile()) { try { diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java index cad0768cc..144ee2e32 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java @@ -66,8 +66,8 @@ public interface IXmlWriter extends AutoCloseable { /** * Writes content. - * Calling this method will automatically - * Note that this method does not use CDATA. + * Note that this method does not support CDATA. + * This method automatically excapes characters. * * @param content the content to write * @return this object @@ -77,6 +77,17 @@ public interface IXmlWriter extends AutoCloseable { */ IXmlWriter content(CharSequence content) throws IOException; + /** + * Writes CDATA content. + * + * @param content the content to write + * @return this object + * @throws OperationNotAllowedException + * if called before any call to {@link #openElement} + * or after the first element has been closed + */ + IXmlWriter cdata(CharSequence content) throws IOException; + /** * Closes the last element written. * diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java index 36365a024..909a6c180 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java @@ -514,6 +514,17 @@ private void writeAttributeContent(CharSequence content) throws IOException { writeEscaped(content, true); } + private void prepareForData() throws IOException { + if (elementNames.isEmpty()) { + if (elementsWritten) { + throw new OperationNotAllowedException("Root element has already been closed."); + } + throw new OperationNotAllowedException("An element must be opened before content can be written."); + } + if (inElement) { + writer.write('>'); + } + } /** * Writes content. Calling this method will automatically Note that this method * does not use CDATA. @@ -525,24 +536,31 @@ private void writeAttributeContent(CharSequence content) throws IOException { */ @Override public IXmlWriter content(CharSequence content) throws IOException { - if (elementNames.isEmpty()) { - if (elementsWritten) { - throw new OperationNotAllowedException("Root element has already been closed."); - } - throw new OperationNotAllowedException("An element must be opened before content can be written."); - } - if (inElement) { - writer.write('>'); - } - writeBodyContent(content); + prepareForData(); + writeEscaped(content, false); inElement = false; return this; } - private void writeBodyContent(final CharSequence content) throws IOException { - writeEscaped(content, false); + + /** + * Writes content. Calling this method will automatically Note that this method + * does not use CDATA. + * + * @param content the content to write + * @return this object + * @throws OperationNotAllowedException if called before any call to + * {@link #openElement} or after the first element has been closed + */ + @Override + public IXmlWriter cdata(CharSequence content) throws IOException { + prepareForData(); + writer.write(String.format("",content)); + inElement = false; + return this; } + private void writeEscaped(final CharSequence content, boolean isAttributeContent) throws IOException { final int length = content.length(); for (int i = 0; i < length; i++) { diff --git a/apache-rat-core/src/main/resources/org/apache/rat/default.xml b/apache-rat-core/src/main/resources/org/apache/rat/default.xml index 9041f7495..db2fb2b3d 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/default.xml +++ b/apache-rat-core/src/main/resources/org/apache/rat/default.xml @@ -56,8 +56,7 @@ - + Modified CDDL1 license The contents of this file are subject to the terms of @@ -67,7 +66,7 @@ - + http://dojotoolkit.org/community/licensing.shtml @@ -162,13 +161,15 @@ - + TMF854 Version 1.0 + + + diff --git a/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl b/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl index 2ea353faf..0fbaec048 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl +++ b/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl @@ -26,24 +26,24 @@ Summary ------- Generated at: -Notes: -Binaries: -Archives: -Standards: +Notes: +Binaries: +Archives: +Standards: -Apache Licensed: -Generated Documents: +Apache Licensed: +Generated Documents: JavaDocs are generated, thus a license header is optional. Generated files do not require license headers. - Unknown Licenses - + Unknown Licenses + ***************************************************** Files with unapproved licenses: - + @@ -53,42 +53,51 @@ Files with unapproved licenses: Archives: - + + + ***************************************************** - Files with Apache License headers will be marked AL - Binary files (which do not require any license headers) will be marked B - Compressed archives will be marked A - Notices, licenses etc. will be marked N + Documents with unapproved licenses will start with a '!' + The next character identifies the document type. + + char type + a Archive file + b Binary file + g Generated file + n Notice file + s Standard file + u Unknown file. + + - ! + ! - - - N - A - B - - !!!!! - - - - - + + + + + + + + + + + + ***************************************************** - + Printing headers for text files without a valid license header... - + ===================================================== == File: ===================================================== - + diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java index 8632e0294..7593d2186 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java @@ -20,22 +20,33 @@ +import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; +import java.io.FileInputStream; import java.io.FilenameFilter; import java.io.IOException; import java.io.PrintStream; import java.nio.charset.StandardCharsets; import java.util.Arrays; +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; + import org.apache.commons.cli.CommandLine; import org.apache.commons.cli.DefaultParser; import org.apache.commons.cli.ParseException; import org.apache.commons.io.FileUtils; +import org.apache.rat.testhelpers.TextUtils; +import org.apache.rat.testhelpers.XmlUtils; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; +import org.w3c.dom.Node; +import org.w3c.dom.NodeList; public class ReportTest { @Test @@ -69,21 +80,105 @@ public void testOutputOption() throws Exception { @Test public void testDefaultOutput() throws Exception { + File output = new File("target/sysout"); + output.delete(); PrintStream origin = System.out; try { - File output = new File("target/sysout"); System.setOut(new PrintStream(output)); CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[]{}); ReportConfiguration config = Report.createConfiguration("target/test-classes/elements", cl); Reporter.report(config); + } finally { + System.setOut(origin); + } assertTrue(output.exists()); String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); - assertTrue(content.contains("2 Unknown Licenses")); - assertTrue(content.contains("target/test-classes/elements/Source.java")); - assertTrue(content.contains("target/test-classes/elements/sub/Empty.txt")); + TextUtils.isMatching("Notes: 2$", content); + TextUtils.isMatching("Binaries: 2$", content); + TextUtils.isMatching("Archives: 1$", content); + TextUtils.isMatching("Standards: 8$", content); + TextUtils.isMatching("Apache Licensed: 5$", content); + TextUtils.isMatching("Generated Documents 1$", content); + TextUtils.isMatching("^2 Unknown licenses", content); + assertTrue(content.contains(" s target/test-classes/elements/ILoggerFactory.java")); + assertTrue(content.contains(" b target/test-classes/elements/Image.png")); + assertTrue(content.contains(" n target/test-classes/elements/LICENSE")); + assertTrue(content.contains(" n target/test-classes/elements/NOTICE")); + assertTrue(content.contains("!s target/test-classes/elements/Source.java")); + assertTrue(content.contains(" s target/test-classes/elements/Text.txt")); + assertTrue(content.contains(" s target/test-classes/elements/TextHttps.txt")); + assertTrue(content.contains(" s target/test-classes/elements/Xml.xml")); + assertTrue(content.contains(" s target/test-classes/elements/buildr.rb")); + assertTrue(content.contains(" a target/test-classes/elements/dummy.jar")); + assertTrue(content.contains(" b target/test-classes/elements/plain.json")); + assertTrue(content.contains("!s target/test-classes/elements/sub/Empty.txt")); + assertTrue(content.contains(" s target/test-classes/elements/tri.txt")); + assertTrue(content.contains(" g target/test-classes/elements/generated.txt")); + } + + @Test + public void testXMLOutput() throws Exception { + + File output = new File("target/sysout"); + output.delete(); + PrintStream origin = System.out; + try { + System.setOut(new PrintStream(output)); + CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[]{"-x"}); + ReportConfiguration config = Report.createConfiguration("target/test-classes/elements", cl); + Reporter.report(config); } finally { System.setOut(origin); } - } + assertTrue(output.exists()); + String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); + Document doc = XmlUtils.toDom(new FileInputStream(output)); + XPath xPath = XPathFactory.newInstance().newXPath(); + + NodeList nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@approval='false']"); + assertEquals(2, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='AL']"); + assertEquals(5, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='MIT']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='BSD-3']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='TMF']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='?????']"); + assertEquals(2, nodeList.getLength()); + + // generated, unknown, archive, notice, binary, standard + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='standard']"); + assertEquals(8, nodeList.getLength()); + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='archive']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='binary']"); + assertEquals(2, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='generated']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='unknown']"); + assertEquals(0, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='notice']"); + assertEquals(2, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/sample"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='generated']/license/notes"); + assertEquals(1,nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@name='target/test-classes/elements/Source.java']/sample"); + assertEquals(1,nodeList.getLength()); + } } 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 d675b6994..8af14fc6e 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 @@ -31,19 +31,49 @@ import javax.xml.xpath.XPathFactory; import org.apache.commons.io.filefilter.HiddenFileFilter; +import org.apache.rat.license.ILicenseFamily; import org.apache.rat.test.utils.Resources; +import org.apache.rat.testhelpers.TextUtils; import org.apache.rat.testhelpers.XmlUtils; import org.apache.rat.utils.DefaultLog; import org.apache.rat.walker.DirectoryWalker; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; +import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Tests the output of the Reporter. */ public class ReporterTest { + + /** + * 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 xpath the XPath instance to use. + * @param resource the xpath statement to locate the node. + * @param id the expected family for the node (may be null) + * @param approval the expected approval value (may be null) + * @param type the type of resource located. + * @throws Exception on XPath error. + */ + public static void checkNode(Document doc, XPath xpath, String resource, LicenseInfo licenseInfo, String type, boolean hasSample) throws Exception { + XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']", resource, type)); + if (licenseInfo != null) { + XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s'][@family='%s']",resource, type, licenseInfo.id, licenseInfo.family)); + XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s'][@approval='%s']", resource, type, licenseInfo.id, Boolean.toString(licenseInfo.approval))); + if (licenseInfo.hasNotes) { + XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s']/notes", resource, type, licenseInfo.id)); + } + } + if (hasSample) { + XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/sample", resource, type)); + } + } + @Test public void xmlReportTest() throws Exception { @@ -58,27 +88,30 @@ public void xmlReportTest() throws Exception { configuration.setOut(() -> out); Reporter.report(configuration); Document doc = XmlUtils.toDom(new ByteArrayInputStream(out.toByteArray())); - + XPath xPath = XPathFactory.newInstance().newXPath(); XmlUtils.getNode(doc, xPath, "/rat-report[@timestamp]"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/ILoggerFactory.java", "MIT", "true", "standard"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Image.png", null, null, "binary"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/LICENSE", null, null, "notice"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/NOTICE", null, null, "notice"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Source.java", "?????", "false", "standard"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Text.txt", "AL", "true", "standard"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/TextHttps.txt", "AL", "true", "standard"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/Xml.xml", "AL", "true", "standard"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/buildr.rb", "AL", "true", "standard"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/dummy.jar", null, null, "archive"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/plain.json", null, null, "binary"); - XmlUtils.checkNode(doc, xPath, "src/test/resources/elements/sub/Empty.txt", "?????", "false", "standard"); - + LicenseInfo apacheLic = new LicenseInfo("AL", true, false); + checkNode(doc, xPath, "src/test/resources/elements/ILoggerFactory.java", new LicenseInfo("MIT", true, false), "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/Image.png", null, "binary", false); + checkNode(doc, xPath, "src/test/resources/elements/LICENSE", null, "notice", false); + checkNode(doc, xPath, "src/test/resources/elements/NOTICE", null, "notice", false); + checkNode(doc, xPath, "src/test/resources/elements/Source.java", new LicenseInfo("?????", false, false), "standard", true); + checkNode(doc, xPath, "src/test/resources/elements/Text.txt", apacheLic, "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/TextHttps.txt", apacheLic, "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/Xml.xml", apacheLic, "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/buildr.rb", apacheLic, "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/dummy.jar", null, "archive", false); + checkNode(doc, xPath, "src/test/resources/elements/plain.json", null, "binary", false); + checkNode(doc, xPath, "src/test/resources/elements/sub/Empty.txt", new LicenseInfo("?????", false, false), "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/tri.txt", apacheLic, "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/tri.txt", new LicenseInfo("BSD-3", true, false), "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/tri.txt", new LicenseInfo("TMF", "BSD-3", true, false), "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/generated.txt", new LicenseInfo("GEN", true, true), "generated", false); NodeList nodeList = (NodeList) xPath.compile("/rat-report/resource").evaluate(doc, XPathConstants.NODESET); - assertEquals(12, nodeList.getLength()); - + assertEquals(14, nodeList.getLength()); } private static final String NL = System.getProperty("line.separator"); @@ -89,7 +122,7 @@ public void xmlReportTest() throws Exception { "Generated at: "; @Test - public void plainReportWithArchivesAndUnapprovedLicenses() throws Exception { + public void plainReportTest() throws Exception { Defaults defaults = Defaults.builder().build(); ByteArrayOutputStream out = new ByteArrayOutputStream(); @@ -106,35 +139,75 @@ public void plainReportWithArchivesAndUnapprovedLicenses() throws Exception { assertTrue(document.startsWith(HEADER), "'Generated at' is present in " + document ); // final int generatedAtLineEnd = document.indexOf(NL, HEADER.length()); - find("^Notes: 2$", document); - find("^Binaries: 2$", document); - find("^Archives: 1$", document); - find("^Standards: 7$", document); - find("^Apache Licensed: 4$", document); - find("^Generated Documents: 0$", document); - find("^2 Unknown Licenses$", document); - find("^Files with unapproved licenses:\\s+" - + "src/test/resources/elements/Source.java\\s+" - + "src/test/resources/elements/sub/Empty.txt\\s", + TextUtils.assertPatternInOutput("^Notes: 2$", document); + TextUtils.assertPatternInOutput("^Binaries: 2$", document); + TextUtils.assertPatternInOutput("^Archives: 1$", document); + TextUtils.assertPatternInOutput("^Standards: 8$", document); + TextUtils.assertPatternInOutput("^Apache Licensed: 5$", document); + TextUtils.assertPatternInOutput("^Generated Documents: 1$", document); + TextUtils.assertPatternInOutput("^2 Unknown Licenses$", document); + TextUtils.assertPatternInOutput("^Files with unapproved licenses:\\s+" + + "\\Qsrc/test/resources/elements/Source.java\\E\\s+" + + "\\Qsrc/test/resources/elements/sub/Empty.txt\\E\\s", document); - find("^Archives:\\s+" + "\\+ src/test/resources/elements/dummy.jar\\s*", document); - find("MIT\\s+src/test/resources/elements/ILoggerFactory.java", document); - find("B\\s+src/test/resources/elements/Image.png", document); - find("N\\s+src/test/resources/elements/LICENSE", document); - find("N\\s+src/test/resources/elements/NOTICE", document); - find("!\\Q?????\\E\\s+src/test/resources/elements/Source.java", document); - find("AL\\s+src/test/resources/elements/Text.txt", document); - find("AL\\s+src/test/resources/elements/TextHttps.txt", document); - find("AL\\s+src/test/resources/elements/Xml.xml", document); - find("AL\\s+src/test/resources/elements/buildr.rb", document); - find("A\\s+src/test/resources/elements/dummy.jar", document); - find("B\\s+src/test/resources/elements/plain.json", document); - find("!\\Q?????\\E\\s+src/test/resources/elements/sub/Empty.txt", document); - find("== File: src/test/resources/elements/sub/Empty.txt", document); + TextUtils.assertPatternInOutput("^ a \\Qsrc/test/resources/elements/dummy.jar\\E", document); + TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/ILoggerFactory.java\\E$\\s+^ MIT The MIT License$", document); + TextUtils.assertPatternInOutput("^ b \\Qsrc/test/resources/elements/Image.png\\E", document); + TextUtils.assertPatternInOutput("^ n \\Qsrc/test/resources/elements/LICENSE\\E", document); + TextUtils.assertPatternInOutput("^ n \\Qsrc/test/resources/elements/NOTICE\\E", document); + TextUtils.assertPatternInOutput("^\\Q!s src/test/resources/elements/Source.java\\E$\\s+^ \\Q?????\\E Unknown license$", document); + TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/Text.txt\\E$\\s+^ AL Apache License Version 2.0$", document); + TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/Xml.xml\\E$\\s+^ AL Apache License Version 2.0$", document); + TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/buildr.rb\\E$\\s+^ AL Apache License Version 2.0$", document); + TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/TextHttps.txt\\E$\\s+^ AL Apache License Version 2.0$", document); + TextUtils.assertPatternInOutput("^ b \\Qsrc/test/resources/elements/plain.json\\E", document); + TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/tri.txt\\E$\\s+^ AL Apache License Version 2.0$\\s+ BSD-3 BSD 3 clause$\\s+ TMF The Telemanagement Forum License$", document); + TextUtils.assertPatternInOutput("^\\Q!s src/test/resources/elements/sub/Empty.txt\\E$\\s+^ \\Q?????\\E Unknown license", document); + /* + + s src/test/resources/elements/ILoggerFactory.java + MIT The MIT License + b src/test/resources/elements/Image.png + n src/test/resources/elements/LICENSE + n src/test/resources/elements/NOTICE + !s src/test/resources/elements/Source.java + ????? Unknown license + s src/test/resources/elements/Text.txt + AL Apache License Version 2.0 + s src/test/resources/elements/TextHttps.txt + AL Apache License Version 2.0 + s src/test/resources/elements/Xml.xml + AL Apache License Version 2.0 + s src/test/resources/elements/buildr.rb + AL Apache License Version 2.0 + a src/test/resources/elements/dummy.jar + g src/test/resources/elements/generated.txt + GEN Generated Files + b src/test/resources/elements/plain.json + s src/test/resources/elements/tri.txt + AL Apache License Version 2.0 + BSD-3 BSD 3 clause + TMF The Telemanagement Forum License + !s src/test/resources/elements/sub/Empty.txt + ????? Unknown license + */ } - private void find(String pattern, String document) { - assertTrue( - Pattern.compile(pattern, Pattern.MULTILINE).matcher(document).find(), () ->String.format("Could not find '%s'", pattern)); + private class LicenseInfo { + String id; + String family; + boolean approval; + boolean hasNotes; + + LicenseInfo(String id, boolean approval, boolean hasNotes) { + this(id, id, approval, hasNotes); + } + + LicenseInfo(String id, String family, boolean approval, boolean hasNotes) { + this.id = id; + this.family = ILicenseFamily.makeCategory(family); + this.approval = approval; + this.hasNotes = hasNotes; + } } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java index 7a4e79ee7..235090b0a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/AnalyserFactoryTest.java @@ -20,13 +20,23 @@ import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; import static org.mockito.ArgumentMatchers.any; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; +import java.io.File; +import java.io.PrintStream; import java.io.StringWriter; +import java.nio.charset.StandardCharsets; import java.util.Arrays; +import org.apache.commons.cli.CommandLine; +import org.apache.commons.cli.DefaultParser; +import org.apache.commons.io.FileUtils; +import org.apache.rat.Report; +import org.apache.rat.ReportConfiguration; +import org.apache.rat.Reporter; import org.apache.rat.document.IDocumentAnalyser; import org.apache.rat.document.impl.MonolithicFileDocument; import org.apache.rat.license.ILicense; @@ -40,7 +50,7 @@ public class AnalyserFactoryTest { - private static ILicense MATCHES_NOTHING_MATCHER = new UnknownLicense(); + private static ILicense MATCHES_NOTHING_MATCHER = UnknownLicense.INSTANCE; private StringWriter out; private SimpleXmlClaimReporter reporter; @@ -61,7 +71,9 @@ public void standardTypeAnalyser() throws Exception { analyser.analyse(document); reporter.report(document); assertEquals( // - "/*\n" + "" + + "" + + "", + + " ]]>", out.toString(), "Open standard element"); } @@ -86,7 +98,7 @@ public void noteTypeAnalyser() throws Exception { Resources.getResourceFile("/elements/LICENSE")); analyser.analyse(document); reporter.report(document); - assertEquals("", + assertEquals("", out.toString(), "Open note element"); } @@ -97,7 +109,7 @@ public void binaryTypeAnalyser() throws Exception { analyser.analyse(document); reporter.report(document); assertEquals( - "", + "", out.toString(), "Open binary element"); } @@ -108,7 +120,7 @@ public void archiveTypeAnalyser() throws Exception { analyser.analyse(document); reporter.report(document); assertEquals( - "", out.toString(), "Open archive element"); + "", out.toString(), "Open archive element"); } @Test @@ -118,6 +130,6 @@ public void archiveTypeAnalyserIntelliJ() throws Exception { analyser.analyse(document); reporter.report(document); assertEquals( - "", out.toString(), "Open archive element"); + "", out.toString(), "Open archive element"); } } 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 53374e036..8dcfdf371 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 @@ -19,10 +19,8 @@ package org.apache.rat.analysis; -import static org.junit.jupiter.api.Assertions.assertTrue; -import static org.junit.jupiter.api.Assertions.assertFalse; - import java.io.StringReader; +import java.util.Arrays; import org.apache.rat.api.Document; import org.apache.rat.license.ILicense; @@ -37,7 +35,7 @@ public class HeaderCheckWorkerTest { public void isFinished() throws Exception { final Document subject = new TestingLocation("subject"); ILicense matcher = new TestingLicense(); - HeaderCheckWorker worker = new HeaderCheckWorker(new StringReader(""), matcher, subject); + HeaderCheckWorker worker = new HeaderCheckWorker(new StringReader(""), Arrays.asList(matcher), subject); worker.read(); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java index 0a22ad65e..ada468586 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/license/AbstractLicenseTest.java @@ -81,37 +81,20 @@ protected ILicense extractCategory(String id) { @MethodSource("parameterProvider") public void testMatchProcessing(String id, String familyPattern, String name, String notes, String[][] targets) throws IOException { ILicense license = extractCategory(id); - String family = ILicenseFamily.makeCategory(familyPattern); - try { - for (String[] target : targets) { - if (processText(license, target[TEXT])) { - data.reportOnLicense(license); - assertNotNull(data.get(MetaData.RAT_URL_HEADER_CATEGORY),"No URL HEADER CATEGORY"); - assertEquals(family, - data.get(MetaData.RAT_URL_HEADER_CATEGORY).getValue(), license.toString()); - assertNotNull(data.get(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY), "No URL LICENSE FAMILY CATEGORY"); - assertEquals(family, - data.get(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY).getValue(), license.toString()); - if (StringUtils.isNotBlank(notes)) { - assertNotNull(data.get(MetaData.RAT_URL_HEADER_SAMPLE), "No URL HEADER SAMPLE"); - assertEquals(FullTextMatcher.prune(notes), - FullTextMatcher.prune(data.get(MetaData.RAT_URL_HEADER_SAMPLE).getValue()), license.toString()); - } else { - assertNull(data.get(MetaData.RAT_URL_HEADER_SAMPLE), "URL HEADER SAMPLE was not null"); - } - assertNotNull(data.get(MetaData.RAT_URL_LICENSE_FAMILY_NAME), "No URL LICENSE FAMILY NAME"); - assertEquals(name, - data.get(MetaData.RAT_URL_LICENSE_FAMILY_NAME).getValue(), license.toString()); - data.clear(); - } else { - fail(license + " was not matched by " + target[NAME]); - } - license.reset(); + try { + for (String[] target : targets) { + if (processText(license, target[TEXT])) { + data.reportOnLicense(license); + assertEquals( 1, data.licenses().count() ); + assertEquals( license, data.licenses().findFirst().get()); + } else { + fail(license + " was not matched by " + target[NAME]); } - } finally { license.reset(); } - + } finally { + license.reset(); + } } private boolean processText(ILicense license, String text) throws IOException { diff --git a/apache-rat-core/src/test/java/org/apache/rat/policy/DefaultPolicyTest.java b/apache-rat-core/src/test/java/org/apache/rat/policy/DefaultPolicyTest.java index 8bb86e0e0..219ed9af7 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/policy/DefaultPolicyTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/policy/DefaultPolicyTest.java @@ -28,7 +28,6 @@ import org.apache.rat.Defaults; import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; -import org.apache.rat.api.MetaData.Datum; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.LicenseFamilySetFactory; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; @@ -73,8 +72,8 @@ public void setUp() throws Exception { } private void assertApproval(boolean pApproved) { - assertEquals(pApproved, MetaData.RAT_APPROVED_LICENSE_VALUE_TRUE - .equals(document.getMetaData().value(MetaData.RAT_URL_APPROVED_LICENSE))); + boolean state = document.getMetaData().approvedLicenses().count() > 0; + assertEquals(pApproved, state); } private void setMetadata(ILicenseFamily family) { @@ -88,7 +87,7 @@ private static ILicenseFamily makeFamily(String category, String name) { @Test public void testCount() { - assertEquals(NUMBER_OF_DEFAULT_ACCEPTED_LICENSES, policy.getApprovedLicenseNames().size()); + assertEquals(NUMBER_OF_DEFAULT_ACCEPTED_LICENSES, policy.getApprovedLicenseFamilies().size()); } @Test @@ -133,7 +132,7 @@ public void testAddNewApprovedLicenseAndDefaults() { assertApproval(false); policy.add(testingFamily); - assertNotNull(LicenseFamilySetFactory.search(testingFamily, policy.getApprovedLicenseNames()), "Did not properly add ILicenseFamily"); + assertNotNull(LicenseFamilySetFactory.search(testingFamily, policy.getApprovedLicenseFamilies()), "Did not properly add ILicenseFamily"); policy.analyse(document); assertApproval(true); } @@ -141,52 +140,35 @@ public void testAddNewApprovedLicenseAndDefaults() { @Test public void testAddNewApprovedLicenseNoDefaults() { policy = new DefaultPolicy(Collections.emptySet()); - assertEquals(0, policy.getApprovedLicenseNames().size()); + assertEquals(0, policy.getApprovedLicenseFamilies().size()); ILicenseFamily testingFamily = makeFamily("test", "Testing License Family"); setMetadata(testingFamily); policy.analyse(document); assertApproval(false); policy.add(testingFamily); - assertEquals(1, policy.getApprovedLicenseNames().size()); - assertNotNull(LicenseFamilySetFactory.search(testingFamily, policy.getApprovedLicenseNames()), "Did not properly add ILicenseFamily"); + assertEquals(1, policy.getApprovedLicenseFamilies().size()); + assertNotNull(LicenseFamilySetFactory.search(testingFamily, policy.getApprovedLicenseFamilies()), "Did not properly add ILicenseFamily"); policy.analyse(document); assertApproval(true); } @Test public void testNonStandardDocumentsDoNotFailLicenseTests() { - Datum[] nonStandardDocuments = { - MetaData.RAT_DOCUMENT_CATEGORY_DATUM_NOTICE, - MetaData.RAT_DOCUMENT_CATEGORY_DATUM_ARCHIVE, - MetaData.RAT_DOCUMENT_CATEGORY_DATUM_BINARY - }; + Document.Type[] nonStandardDocuments = { Document.Type.notice, Document.Type.archive, Document.Type.binary }; - for (Datum d : nonStandardDocuments) { + for (Document.Type d : nonStandardDocuments) { document = new TestingLocation("subject"); - document.getMetaData().set(d); + document.getMetaData().setDocumentType(d); policy.analyse(document); - assertNull( document.getMetaData().get(MetaData.RAT_URL_APPROVED_LICENSE), "failed on "+d.getValue()); + assertEquals( 0, document.getMetaData().licenses().count(), "failed on "+d); } } @Test public void testUnclassifiedDocumentsDoNotFailLicenseTests() { - document.getMetaData().set(MetaData.RAT_DOCUMENT_CATEGORY_DATUM_STANDARD); + document.getMetaData().setDocumentType(Document.Type.standard); policy.analyse(document); assertApproval( false ); } - - @Test - public void testReportLicenseApprovalClaim() { - assertNull( document.getMetaData().get(MetaData.RAT_URL_APPROVED_LICENSE)); - - - policy.reportLicenseApprovalClaim(document, false); - assertEquals( MetaData.RAT_APPROVED_LICENSE_DATUM_FALSE, document.getMetaData().get(MetaData.RAT_URL_APPROVED_LICENSE)); - - policy.reportLicenseApprovalClaim(document, true); - assertEquals( MetaData.RAT_APPROVED_LICENSE_DATUM_TRUE, document.getMetaData().get(MetaData.RAT_URL_APPROVED_LICENSE)); - - } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java index 462c110de..1a4a4976a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportFactoryTest.java @@ -33,6 +33,7 @@ import org.apache.commons.io.filefilter.HiddenFileFilter; import org.apache.rat.ConfigurationException; import org.apache.rat.ReportConfiguration; +import org.apache.rat.api.Document; import org.apache.rat.api.MetaData; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -90,14 +91,10 @@ public void standardReport() throws Exception { output.startsWith("" + " reporters = new ArrayList<>(); - reporters.add(reporter); - report = new ClaimReporterMultiplexer(analyser, reporters); - } - - private void report(DirectoryWalker directory) throws Exception { - directory.run(report); - } - - @Test - public void baseReport() throws Exception { - final String elementsPath = Resources.getResourceDirectory("elements/Source.java"); - DirectoryWalker directory = new DirectoryWalker(new File(elementsPath), IGNORE, HiddenFileFilter.HIDDEN); - report.startReport(); - report(directory); - report.endReport(); - writer.closeDocument(); - final String output = out.toString(); - assertTrue(output.startsWith("" + ""Output does not match string: " + pPattern+"\n"+out); + isMatching(pattern, out), ()->"Output does not match string: " + pattern+"\n"+out); } - public static void assertPatternNotInOutput(String pPattern, String out) { + public static void assertPatternNotInOutput(String pattern, String out) { assertFalse( - isMatching(pPattern, out), ()->"Output matches the pattern: " + pPattern+"\n"+out); + isMatching(pattern, out), ()->"Output matches the pattern: " + pattern+"\n"+out); } - public static boolean isMatching(final String pPattern, final String pValue) { - return Pattern.compile(pPattern, Pattern.MULTILINE).matcher(pValue).find(); + public static boolean isMatching(final String pattern, final String value) { + return Pattern.compile(pattern, Pattern.MULTILINE).matcher(value).find(); } + + public static void find(String pattern, String document) { + assertTrue( + Pattern.compile(pattern, Pattern.MULTILINE).matcher(document).find(), () ->String.format("Could not find '%s'", pattern)); + } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java index 230a965a1..f36263cd6 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/XmlUtils.java @@ -47,6 +47,7 @@ import org.apache.rat.license.ILicenseFamily; import org.apache.rat.report.xml.writer.IXmlWriter; import org.w3c.dom.Document; +import org.w3c.dom.NamedNodeMap; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import org.xml.sax.InputSource; @@ -61,17 +62,22 @@ private XmlUtils() { // Does nothing } - public static final boolean isWellFormedXml(final String string) throws Exception { - return isWellFormedXml(new InputSource(new StringReader(string))); - } - + public static final XMLReader newXMLReader() throws SAXException, ParserConfigurationException { final SAXParserFactory spf = SAXParserFactory.newInstance(); spf.setValidating(false); spf.setNamespaceAware(true); return spf.newSAXParser().getXMLReader(); } + + public static final boolean isWellFormedXml(final String string) throws Exception { + return isWellFormedXml(new InputSource(new StringReader(string))); + } + public static final boolean isWellFormedXml(final InputStream in) throws Exception { + return isWellFormedXml(new InputSource(in)); + } + public static final boolean isWellFormedXml(final InputSource isource) { try { newXMLReader().parse(isource); @@ -84,44 +90,33 @@ public static final boolean isWellFormedXml(final InputSource isource) { } } - /** - * 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 xpath the XPath instance to use. - * @param resource the xpath statement to locate the node. - * @param family the expected family for the node (may be null) - * @param approval the expected approval value (may be null) - * @param type the type of resource located. - * @return The node that was located - * @throws Exception on XPath error. - */ - public static Node checkNode(Document doc, XPath xpath, String resource, String family, String approval, - String type) throws Exception { - Node root = getNode(doc, xpath, String.format("/rat-report/resource[@name='%s']", resource)); - if (family != null) { - getNode(root, xpath, String.format("header-type[@name='%s']", ILicenseFamily.makeCategory(family))); - getNode(root, xpath, "license-family[@name]"); - if (family.equals("?????")) { - getNode(root, xpath, "header-sample"); - } - } - if (approval != null) { - getNode(root, xpath, String.format("license-approval[@name='%s']", approval)); - } - getNode(root, xpath, String.format("type[@name='%s']", type)); - return root; + public static NodeList getNodeList(Object source, XPath xPath, String xpath) throws XPathExpressionException { + return (NodeList) xPath.compile(xpath).evaluate(source, XPathConstants.NODESET); } - + + public static boolean isPresent(Object source, XPath xPath, String xpath) throws XPathExpressionException { + return !xPath.compile(xpath).evaluate(source).equals("null"); + } + public static Node getNode(Object source, XPath xPath, String xpath) throws XPathExpressionException { - NodeList nodeList = (NodeList) xPath.compile(xpath).evaluate(source, XPathConstants.NODESET); + NodeList nodeList = getNodeList(source, xPath, xpath); assertEquals(1, nodeList.getLength(), "Could not find " + xpath); return nodeList.item(0); } - public static final boolean isWellFormedXml(final InputStream in) throws Exception { - return isWellFormedXml(new InputSource(in)); + public static final String printNodeList(NodeList nodeList) { + StringBuilder sb = new StringBuilder(); + for (int i=0;i Date: Fri, 29 Mar 2024 15:29:40 +0100 Subject: [PATCH 08/77] added Unapporved licensce report test and added examples of output --- .../rat/analysis/DocumentHeaderAnalyser.java | 11 +- .../rat/analysis/HeaderCheckWorker.java | 9 +- .../java/org/apache/rat/api/Document.java | 2 +- .../java/org/apache/rat/api/MetaData.java | 250 ++---------------- .../org/apache/rat/unapproved-licenses.xsl | 5 +- .../java/org/apache/rat/ReporterTest.java | 55 ++-- .../src/site/examples/default_output.txt | 67 +++++ apache-rat/src/site/examples/rat-report.txt | 49 ++++ .../src/site/examples/unapproved-licenses.txt | 0 9 files changed, 172 insertions(+), 276 deletions(-) create mode 100644 apache-rat/src/site/examples/default_output.txt create mode 100644 apache-rat/src/site/examples/rat-report.txt create mode 100644 apache-rat/src/site/examples/unapproved-licenses.txt 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 6c0ad1824..659a74c01 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 @@ -18,18 +18,17 @@ */ package org.apache.rat.analysis; +import static java.lang.String.format; + import java.io.IOException; import java.io.Reader; import java.util.Collection; import org.apache.rat.api.Document; import org.apache.rat.document.IDocumentAnalyser; -import org.apache.rat.document.RatDocumentAnalysisException; import org.apache.rat.license.ILicense; import org.apache.rat.utils.Log; -import static java.lang.String.format; - /** * A Document analyzer that analyses document headers for a license. */ @@ -42,7 +41,7 @@ class DocumentHeaderAnalyser implements IDocumentAnalyser { /** * Constructs the HeaderAnalyser for the specific license. - * + * * @param license The license to analyse */ public DocumentHeaderAnalyser(final Log log, final Collection licenses) { @@ -58,10 +57,10 @@ public void analyse(Document document) { HeaderCheckWorker worker = new HeaderCheckWorker(reader, licenses, document); worker.read(); } catch (IOException e) { - log.warn(String.format("Can not read header of %s",document)); + log.warn(String.format("Can not read header of %s", document)); document.getMetaData().setDocumentType(Document.Type.unknown); } catch (RatHeaderAnalysisException e) { - log.warn(String.format("Can not process header of %s",document)); + log.warn(String.format("Can not process header of %s", document)); document.getMetaData().setDocumentType(Document.Type.unknown); } } 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 30d25fa54..81428bd21 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 @@ -28,7 +28,6 @@ import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.matchers.FullTextMatcher; import org.apache.rat.api.Document; -import org.apache.rat.api.MetaData; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -132,14 +131,14 @@ public void read() throws RatHeaderAnalysisException { final IHeaders headers = readHeader(reader, numberOfRetainedHeaderLines); licenses.stream().filter(lic -> lic.matches(headers)).forEach(document.getMetaData()::reportOnLicense); if (document.getMetaData().detectedLicense()) { - if (document.getMetaData().licenses().anyMatch( lic -> lic.getLicenseFamily().getFamilyCategory().equals(ILicenseFamily.GENTERATED_CATEGORY))) { + if (document.getMetaData().licenses().anyMatch( + lic -> ILicenseFamily.GENTERATED_CATEGORY.equals(lic.getLicenseFamily().getFamilyCategory()))) { document.getMetaData().setDocumentType(Document.Type.generated); } - } - else { + } else { document.getMetaData().reportOnLicense(UnknownLicense.INSTANCE); document.getMetaData().setSampleHeader(headers.raw()); - } + } } catch (IOException e) { throw new RatHeaderAnalysisException("Cannot read header for " + document, e); } finally { diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java index 0f99c4a4b..85aa09558 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java +++ b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java @@ -26,7 +26,7 @@ public interface Document { - enum Type {generated, unknown, archive, notice, binary, standard}; + enum Type {generated, unknown, archive, notice, binary, standard} /** * @return the name of the current document. diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java index 47b5b4921..316bda5b2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java +++ b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java @@ -18,20 +18,12 @@ */ package org.apache.rat.api; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.Iterator; -import java.util.List; -import java.util.Objects; -import java.util.Set; import java.util.HashSet; -import java.util.TreeSet; +import java.util.Set; import java.util.SortedSet; +import java.util.TreeSet; import java.util.stream.Stream; -import org.apache.commons.lang3.StringUtils; -import org.apache.rat.analysis.UnknownLicense; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -39,122 +31,64 @@ * Data about the document under test.. */ public class MetaData { - - - - public static final String RAT_BASE_URL = "http://org/apache/rat/meta-data"; - - // Document Categories - public static final String RAT_URL_DOCUMENT_CATEGORY = RAT_BASE_URL + "#FileCategory"; -// public static final String RAT_DOCUMENT_CATEGORY_VALUE_GENERATED = "GEN "; -// public static final String RAT_DOCUMENT_CATEGORY_VALUE_UNKNOWN = "?????"; -// public static final String RAT_DOCUMENT_CATEGORY_VALUE_ARCHIVE = "archive"; -// public static final String RAT_DOCUMENT_CATEGORY_VALUE_NOTICE = "notice"; -// public static final String RAT_DOCUMENT_CATEGORY_VALUE_BINARY = "binary"; -// public static final String RAT_DOCUMENT_CATEGORY_VALUE_STANDARD = "standard"; -// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_GENERATED = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_GENERATED); -// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_UNKNOWN = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_UNKNOWN); -// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_ARCHIVE = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_ARCHIVE); -// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_NOTICE = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_NOTICE); -// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_BINARY = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_BINARY); -// public static final Datum RAT_DOCUMENT_CATEGORY_DATUM_STANDARD = new Datum(RAT_URL_DOCUMENT_CATEGORY, RAT_DOCUMENT_CATEGORY_VALUE_STANDARD); - - // Header Categories - //public static final String RAT_URL_HEADER_CATEGORY = RAT_BASE_URL + "#HeaderCategory"; - - // License Family Categories - //public static final String RAT_URL_LICENSE_FAMILY_CATEGORY= RAT_BASE_URL + "#LicenseFamilyCategory"; - // Shortcuts used in report output, must be exactly 5 characters - // public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN = "GEN "; - //public static final String RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN = "?????"; - - - //public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_GEN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_GEN); - //public static final Datum RAT_LICENSE_FAMILY_CATEGORY_DATUM_UNKNOWN = new Datum(RAT_URL_LICENSE_FAMILY_CATEGORY, RAT_LICENSE_FAMILY_CATEGORY_VALUE_UNKNOWN); - - - // License Family Standard Names - // public static final String RAT_URL_LICENSE_FAMILY_NAME= RAT_BASE_URL + "#LicenseFamilyName"; - - - - //public static final String RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN = "?????"; - - - //public static final Datum RAT_LICENSE_FAMILY_NAME_DATUM_UNKNOWN - // = new Datum(RAT_URL_LICENSE_FAMILY_NAME, RAT_LICENSE_FAMILY_NAME_VALUE_UNKNOWN); - - // Header sample - public static final String RAT_URL_HEADER_SAMPLE = RAT_BASE_URL + "#HeaderSample"; - - // License Approval - public static final String RAT_URL_APPROVED_LICENSE = RAT_BASE_URL + "#ApprovedLicense"; - public static final String RAT_APPROVED_LICENSE_VALUE_TRUE = Boolean.TRUE.toString(); - public static final String RAT_APPROVED_LICENSE_VALUE_FALSE = Boolean.FALSE.toString(); -// public static final Datum RAT_APPROVED_LICENSE_DATUM_TRUE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_TRUE); -// public static final Datum RAT_APPROVED_LICENSE_DATUM_FALSE = new Datum(RAT_URL_APPROVED_LICENSE, RAT_APPROVED_LICENSE_VALUE_FALSE); - - /** - * Only likely to be a small quantity of data - * so trade some performance for simplicity. - */ - // private final List data; /** The list of matched licenses */ private final SortedSet matchedLicenses; + /** The list of License Family Categories that are approved */ private final Set approvedLicenses; - + private Document.Type documentType; private String sampleHeader; + /** * Create metadata without a content type. */ public MetaData() { this.matchedLicenses = new TreeSet<>(); this.approvedLicenses = new HashSet<>(); - // this.data = new ArrayList<>(16); } - + public boolean detectedLicense() { return !matchedLicenses.isEmpty(); } - + public void setApprovedLicenses(Set approvedLicenseFamilies) { - licenses().filter( lic -> approvedLicenseFamilies.contains(lic.getLicenseFamily())).forEach(lic -> approvedLicenses.add(lic.getId())); + licenses().filter(lic -> approvedLicenseFamilies.contains(lic.getLicenseFamily())) + .forEach(lic -> approvedLicenses.add(lic.getId())); } - + public Stream licenses() { return matchedLicenses.stream(); } - + public Stream approvedLicenses() { return licenses().filter(this::isApproved); } - + public boolean isApproved(ILicense license) { return approvedLicenses.contains(license.getId()); } - + public Stream unapprovedLicenses() { - return licenses().filter( lic -> !isApproved(lic)); + return licenses().filter(lic -> !isApproved(lic)); } public void setSampleHeader(String sampleHeader) { this.sampleHeader = sampleHeader; } - + public String getSampleHeader() { return sampleHeader; } - + public void setDocumentType(Document.Type type) { this.documentType = type; } - + public Document.Type getDocumentType() { return this.documentType; } - + /** * Add the license information to the metadata. * @param license the license to add metadata for. @@ -162,152 +96,4 @@ public Document.Type getDocumentType() { public void reportOnLicense(ILicense license) { this.matchedLicenses.add(license); } -// if (StringUtils.isNotBlank(license.getNotes())) { -// set(new MetaData.Datum(MetaData.RAT_URL_HEADER_SAMPLE, license.getNotes())); -// } -// set(new MetaData.Datum(MetaData.RAT_URL_HEADER_CATEGORY, license.getLicenseFamily().getFamilyCategory())); -// set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_CATEGORY, license.getLicenseFamily().getFamilyCategory())); -// set(new MetaData.Datum(MetaData.RAT_URL_LICENSE_FAMILY_NAME, license.getLicenseFamily().getFamilyName())); - - - -// /** -// * Gets all data. -// * @return unmodifiable view of the meta data. -// */ -// public Collection getData() { -// return Collections.unmodifiableCollection(data); -// } -// -// /** -// * Adds a new datum. -// * Existing data with the same name are not replaced. -// * @param datum datum to add. -// * @see #set(org.apache.rat.api.MetaData.Datum) -// */ -// public void add(final Datum datum) { -// data.add(datum); -// } -// -// /** -// * Puts in a new datum replacing any existing data. -// * Any current data matching the name are removed. -// * @param datum not null -// * @see #add(org.apache.rat.api.MetaData.Datum) -// */ -// public void set(final Datum datum) { -// clear(datum.getName()); -// add(datum); -// } -// -// /** -// * Gets the first datum matching the given name. -// * @param name not null -// * @return the matching datum first added when there is any matching data, -// * null otherwise -// */ -// public Datum get(final String name) { -// Datum result = null; -// for (Datum next : data) { -// if (name.equals(next.getName())) { -// result = next; -// break; -// } -// } -// return result; -// } -// -// /** -// * Gets the value of the first datum matching the given name. -// * @param name not null -// * @return the value of the matchin datum first added when there is any matching data, -// * null otherwise -// */ -// public String value(final String name) { -// final Datum datum = get(name); -// final String result; -// if (datum == null) { -// result = null; -// } else { -// result = datum.getValue(); -// } -// return result; -// } -// -// /** -// * Removes all data matching the given name. -// * @param name not null -// * @return true if any data match, false otherwise -// */ -// public boolean clear(final String name) { -// boolean dataRemoved = false; -// for (final Iterator it = data.iterator();it.hasNext();) { -// final Datum datum = it.next(); -// if (datum.getName().equals(name)) { -// it.remove(); -// dataRemoved = true; -// } -// } -// return dataRemoved; -// } -// -// /** -// * Clears all data. -// */ -// public void clear() { -// data.clear(); -// } -// -// /** -// * A datum. -// */ -// public static final class Datum { -// private final String name; -// private final String value; -// -// /** -// * Constructs a datum. -// * @param name not null -// * @param value not null -// */ -// public Datum(final String name, final String value) { -// super(); -// this.name = name; -// this.value = value; -// } -// -// /** -// * Gets the name of the data type. -// * To avoid collisions, it is recommended that URLs are used. -// * @return not null -// */ -// public String getName() { -// return name; -// } -// -// /** -// * Data type value. -// * @return not null -// */ -// public String getValue() { -// return value; -// } -// -// /** -// * Constructs a String with all attributes -// * in name = value format. -// * -// * @return a String representation -// * of this object. -// */ -// @Override -// public String toString() -// { -// return "Datum [ " -// + "name ='" + this.name + "'," -// + "value ='" + this.value + " " -// + "']"; -// } -// } } - \ No newline at end of file diff --git a/apache-rat-core/src/main/resources/org/apache/rat/unapproved-licenses.xsl b/apache-rat-core/src/main/resources/org/apache/rat/unapproved-licenses.xsl index 040909b4c..b82b6a148 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/unapproved-licenses.xsl +++ b/apache-rat-core/src/main/resources/org/apache/rat/unapproved-licenses.xsl @@ -20,8 +20,9 @@ -Files with unapproved licenses: - +Generated at: +Files with unapproved licenses: + 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 8af14fc6e..9f8626ad9 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 @@ -136,9 +136,8 @@ public void plainReportTest() throws Exception { out.flush(); String document = out.toString(); - assertTrue(document.startsWith(HEADER), "'Generated at' is present in " + document ); + assertTrue(document.startsWith(HEADER), "'Generated at' is not present in " + document ); - // final int generatedAtLineEnd = document.indexOf(NL, HEADER.length()); TextUtils.assertPatternInOutput("^Notes: 2$", document); TextUtils.assertPatternInOutput("^Binaries: 2$", document); TextUtils.assertPatternInOutput("^Archives: 1$", document); @@ -163,35 +162,31 @@ public void plainReportTest() throws Exception { TextUtils.assertPatternInOutput("^ b \\Qsrc/test/resources/elements/plain.json\\E", document); TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/tri.txt\\E$\\s+^ AL Apache License Version 2.0$\\s+ BSD-3 BSD 3 clause$\\s+ TMF The Telemanagement Forum License$", document); TextUtils.assertPatternInOutput("^\\Q!s src/test/resources/elements/sub/Empty.txt\\E$\\s+^ \\Q?????\\E Unknown license", document); - /* - - s src/test/resources/elements/ILoggerFactory.java - MIT The MIT License - b src/test/resources/elements/Image.png - n src/test/resources/elements/LICENSE - n src/test/resources/elements/NOTICE - !s src/test/resources/elements/Source.java - ????? Unknown license - s src/test/resources/elements/Text.txt - AL Apache License Version 2.0 - s src/test/resources/elements/TextHttps.txt - AL Apache License Version 2.0 - s src/test/resources/elements/Xml.xml - AL Apache License Version 2.0 - s src/test/resources/elements/buildr.rb - AL Apache License Version 2.0 - a src/test/resources/elements/dummy.jar - g src/test/resources/elements/generated.txt - GEN Generated Files - b src/test/resources/elements/plain.json - s src/test/resources/elements/tri.txt - AL Apache License Version 2.0 - BSD-3 BSD 3 clause - TMF The Telemanagement Forum License - !s src/test/resources/elements/sub/Empty.txt - ????? Unknown license - */ } + + + @Test + public void UnapprovedLicensesReportTest() throws Exception { + Defaults defaults = Defaults.builder().build(); + ByteArrayOutputStream out = new ByteArrayOutputStream(); + + final String elementsPath = Resources.getResourceDirectory("elements/Source.java"); + final ReportConfiguration configuration = new ReportConfiguration(DefaultLog.INSTANCE); + configuration.setFrom(defaults); + configuration.setReportable(new DirectoryWalker(new File(elementsPath), HiddenFileFilter.HIDDEN)); + configuration.setOut(() -> out); + configuration.setStyleSheet(this.getClass().getResource("/org/apache/rat/unapproved-licenses.xsl")); + Reporter.report(configuration); + + out.flush(); + String document = out.toString(); + + assertTrue(document.startsWith("Generated at: "), "'Generated at' is not present in " + document ); + + TextUtils.assertPatternInOutput("\\Qsrc/test/resources/elements/Source.java\\E$", document); + TextUtils.assertPatternInOutput("\\Qsrc/test/resources/elements/sub/Empty.txt\\E", document); + } + private class LicenseInfo { String id; diff --git a/apache-rat/src/site/examples/default_output.txt b/apache-rat/src/site/examples/default_output.txt new file mode 100644 index 000000000..65a63a4e0 --- /dev/null +++ b/apache-rat/src/site/examples/default_output.txt @@ -0,0 +1,67 @@ + +***************************************************** +Summary +------- +Generated at: 2024-03-29T15:01:24+01:00 + +Notes: 2 +Binaries: 2 +Archives: 1 +Standards: 8 + +Apache Licensed: 5 +Generated Documents: 1 + +JavaDocs are generated, thus a license header is optional. +Generated files do not require license headers. + +2 Unknown Licenses + +***************************************************** + +Files with unapproved licenses: + + src/test/resources/elements/Source.java + src/test/resources/elements/sub/Empty.txt + +***************************************************** + +***************************************************** + Documents with unapproved licenses will start with a '!' + The next character identifies the document type. + + char type + a Archive file + b Binary file + g Generated file + n Notice file + s Standard file + u Unknown file. + + s src/test/resources/elements/ILoggerFactory.java + MIT The MIT License + b src/test/resources/elements/Image.png + n src/test/resources/elements/LICENSE + n src/test/resources/elements/NOTICE +!s src/test/resources/elements/Source.java + ????? Unknown license + s src/test/resources/elements/Text.txt + AL Apache License Version 2.0 + s src/test/resources/elements/TextHttps.txt + AL Apache License Version 2.0 + s src/test/resources/elements/Xml.xml + AL Apache License Version 2.0 + s src/test/resources/elements/buildr.rb + AL Apache License Version 2.0 + a src/test/resources/elements/dummy.jar + g src/test/resources/elements/generated.txt + GEN Generated Files + b src/test/resources/elements/plain.json + s src/test/resources/elements/tri.txt + AL Apache License Version 2.0 + BSD-3 BSD 3 clause + TMF The Telemanagement Forum License +!s src/test/resources/elements/sub/Empty.txt + ????? Unknown license + +***************************************************** diff --git a/apache-rat/src/site/examples/rat-report.txt b/apache-rat/src/site/examples/rat-report.txt new file mode 100644 index 000000000..d3e1d7521 --- /dev/null +++ b/apache-rat/src/site/examples/rat-report.txt @@ -0,0 +1,49 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apache-rat/src/site/examples/unapproved-licenses.txt b/apache-rat/src/site/examples/unapproved-licenses.txt new file mode 100644 index 000000000..e69de29bb From f4e65d5d0244a8e19a218b449b7f7a252d5b6d57 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sat, 30 Mar 2024 15:29:56 +0100 Subject: [PATCH 09/77] fixed issues with rat maven plugin --- .../src/main/java/org/apache/rat/Report.java | 2 +- .../main/java/org/apache/rat/Reporter.java | 131 +++++++------ .../java/org/apache/rat/api/MetaData.java | 5 + .../java/org/apache/rat/api/RatException.java | 7 + .../builders/CopyrightBuilder.java | 2 +- .../rat/document/impl/FileDocument.java | 7 +- .../xml/writer/impl/base/XmlWriter.java | 7 +- .../resources/org/apache/rat/plain-rat.xsl | 8 +- .../test/java/org/apache/rat/ReportTest.java | 172 +++++++++--------- .../java/org/apache/rat/ReporterTest.java | 120 +++++++----- .../java/org/apache/rat/mp/Copyright.java | 3 +- .../org/apache/rat/mp/FilesReportable.java | 47 +---- .../java/org/apache/rat/mp/RatCheckMojo.java | 43 +++-- .../java/org/apache/rat/mp/RatReportMojo.java | 3 +- .../org/apache/rat/anttasks/Copyright.java | 3 +- .../java/org/apache/rat/anttasks/Report.java | 2 +- .../anttasks/ResourceCollectionContainer.java | 12 +- .../org/apache/rat/anttasks/ReportTest.java | 40 ++-- .../src/site/examples/default_output.txt | 38 ++-- 19 files changed, 362 insertions(+), 290 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 68129735d..bb783d151 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 @@ -180,7 +180,7 @@ public static void main(String[] args) throws Exception { } if (!dryRun) { - Reporter.report(configuration); + new Reporter(configuration).output(); } } } 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 7a5feb038..610770dbc 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,13 +18,25 @@ */ package org.apache.rat; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; -import java.io.PipedReader; -import java.io.PipedWriter; +import java.io.OutputStream; +import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.io.Writer; +import javax.xml.parsers.DocumentBuilderFactory; +import javax.xml.transform.OutputKeys; +import javax.xml.transform.Transformer; +import javax.xml.transform.TransformerException; +import javax.xml.transform.TransformerFactory; +import javax.xml.transform.dom.DOMSource; +import javax.xml.transform.stream.StreamResult; +import javax.xml.transform.stream.StreamSource; + +import org.apache.commons.io.function.IOSupplier; import org.apache.rat.api.RatException; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; import org.apache.rat.report.RatReport; @@ -32,9 +44,11 @@ import org.apache.rat.report.xml.XmlReportFactory; import org.apache.rat.report.xml.writer.IXmlWriter; import org.apache.rat.report.xml.writer.impl.base.XmlWriter; +import org.w3c.dom.Document; /** - * Class that executes the report as defined in a ReportConfiguration. + * Class that executes the report as defined in a ReportConfiguration and stores + * the result for later handleing. */ public class Reporter { @@ -47,67 +61,75 @@ public class Reporter { * Format used for listing licenses. */ private static final String LICENSE_FORMAT = "%s:\t%s\n\t\t%s\n"; - - private Reporter() { - // Do not instantiate - } - /** - * Execute the report. - * - * @param configuration The report configuration. - * @return the currently collected numerical statistics. - * @throws Exception in case of errors. - */ - public static ClaimStatistic report(ReportConfiguration configuration) throws Exception { - if (configuration.getReportable() != null) { - if (configuration.isStyleReport()) { - try (PipedReader reader = new PipedReader(); - PipedWriter writer = new PipedWriter(reader); - InputStream style = configuration.getStyleSheet().get(); - PrintWriter reportWriter = configuration.getWriter().get();) { - ReportTransformer transformer = new ReportTransformer(reportWriter, style, reader); - Thread transformerThread = new Thread(transformer); - transformerThread.start(); - final ClaimStatistic statistic = report(writer, configuration); - writer.flush(); - writer.close(); - transformerThread.join(); - return statistic; + private final Document document; + private final ClaimStatistic statistic; + private final ReportConfiguration configuration; + + public Reporter(ReportConfiguration configuration) throws RatException { + this.configuration = configuration; + try { + if (configuration.getReportable() != null) { + ByteArrayOutputStream outputStream = new ByteArrayOutputStream(); + Writer outputWriter = new OutputStreamWriter(outputStream); + try (IXmlWriter writer = new XmlWriter(outputWriter)) { + statistic = new ClaimStatistic(); + RatReport report = XmlReportFactory.createStandardReport(writer, statistic, configuration); + report.startReport(); + configuration.getReportable().run(report); + report.endReport(); + + InputStream inputStream = new ByteArrayInputStream(outputStream.toByteArray()); + document = DocumentBuilderFactory.newInstance().newDocumentBuilder().parse(inputStream); } + } else { + document = DocumentBuilderFactory.newInstance().newDocumentBuilder().newDocument(); + statistic = new ClaimStatistic(); } - try (Writer writer = configuration.getWriter().get()) { - return report(writer, configuration); - } + } catch (Exception e) { + throw RatException.makeInstance(e); } - return null; } - /** - * Execute the report. - * @param outputWriter the writer to send output to. - * @param configuration The report configuration. - * @return the currently collected numerical statistics. - * @throws IOException in case of I/O errors. - * @throws RatException in case of internal errors. - */ - private static ClaimStatistic report(Writer outputWriter, ReportConfiguration configuration) - throws IOException, RatException { - try (IXmlWriter writer = new XmlWriter(outputWriter)) { - final ClaimStatistic statistic = new ClaimStatistic(); - RatReport report = XmlReportFactory.createStandardReport(writer, statistic, configuration); - report.startReport(); - configuration.getReportable().run(report); - report.endReport(); - - return statistic; - } catch (Exception e) { - throw new IOException(e); + public ClaimStatistic getClaimsStatistic() { + return statistic; + } + + public void output() throws RatException { + if (configuration.isStyleReport()) { + output(configuration.getStyleSheet(), configuration.getOutput()); + } else { + output(null, configuration.getOutput()); + } + } + + public void output(IOSupplier stylesheet, IOSupplier output) throws RatException { + + TransformerFactory tf = TransformerFactory.newInstance(); + Transformer transformer; + try { + if (stylesheet != null) { + transformer = tf.newTransformer(new StreamSource(stylesheet.get())); + } else { + transformer = tf.newTransformer(); + transformer.setOutputProperty(OutputKeys.OMIT_XML_DECLARATION, "no"); + transformer.setOutputProperty(OutputKeys.METHOD, "xml"); + transformer.setOutputProperty(OutputKeys.INDENT, "yes"); + transformer.setOutputProperty(OutputKeys.ENCODING, "UTF-8"); + transformer.setOutputProperty("{http://xml.apache.org/xslt}indent-amount", "4"); + } + + + transformer.transform(new DOMSource(document), + new StreamResult(new OutputStreamWriter(output.get(), "UTF-8"))); + } catch (TransformerException | IOException e) { + throw new RatException(e); } } - + /** * lists the license families information on the configured output stream. + * * @param configuration The configuration for the system * @throws IOException if PrintWriter can not be retrieved from configuration. */ @@ -122,6 +144,7 @@ public static void listLicenseFamilies(ReportConfiguration configuration, Licens /** * lists the licenses on the configured output stream. + * * @param configuration The configuration for the system * @throws IOException if PrintWriter can not be retrieved from configuration. */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java index 316bda5b2..3a13376b3 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java +++ b/apache-rat-core/src/main/java/org/apache/rat/api/MetaData.java @@ -96,4 +96,9 @@ public Document.Type getDocumentType() { public void reportOnLicense(ILicense license) { this.matchedLicenses.add(license); } + + @Override + public String toString() { + return String.format( "MetaData[%s license, %s approved]", matchedLicenses.size(), approvedLicenses.size()); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java b/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java index 9d5c2c3a0..c89d6bd1f 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java +++ b/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java @@ -22,6 +22,13 @@ public class RatException extends Exception { private static final long serialVersionUID = 4940711222435919034L; + public static RatException makeInstance(Exception e) { + if (e instanceof RatException) { + return (RatException) e; + } + return new RatException(e); + } + public RatException() { super(); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java index f38220ade..73c6e70c4 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java @@ -60,7 +60,7 @@ public CopyrightBuilder setOwner(String owner) { } @Override - public IHeaderMatcher build() { + public CopyrightMatcher build() { return new CopyrightMatcher(getId(), start, end, owner); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/impl/FileDocument.java b/apache-rat-core/src/main/java/org/apache/rat/document/impl/FileDocument.java index d8d32322a..524690e1a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/document/impl/FileDocument.java +++ b/apache-rat-core/src/main/java/org/apache/rat/document/impl/FileDocument.java @@ -44,22 +44,27 @@ public FileDocument(final File file) { name = DocumentImplUtils.toName(file); } + @Override public boolean isComposite() { return DocumentImplUtils.isZip(file); } + @Override public Reader reader() throws IOException { return new FileReader(file); } + @Override public String getName() { return name; } + @Override public MetaData getMetaData() { return metaData; } + @Override public InputStream inputStream() throws IOException { return new FileInputStream(file); } @@ -78,6 +83,4 @@ public String toString() + "metaData = " + this.metaData + " " + " )"; } - - } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java index 909a6c180..b11116628 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java @@ -555,7 +555,12 @@ public IXmlWriter content(CharSequence content) throws IOException { @Override public IXmlWriter cdata(CharSequence content) throws IOException { prepareForData(); - writer.write(String.format("",content)); + StringBuilder sb = new StringBuilder(content); + int found; + while (-1 != (found = sb.indexOf("]]>"))) { + sb.replace(found, found+3, ""); + } + writer.write(String.format("",sb.toString())); inElement = false; return this; } diff --git a/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl b/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl index 0fbaec048..dd88ae724 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl +++ b/apache-rat-core/src/main/resources/org/apache/rat/plain-rat.xsl @@ -83,12 +83,16 @@ Archives: - - + + + + + + ***************************************************** diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java index 7593d2186..8f8d94023 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportTest.java @@ -18,8 +18,6 @@ */ package org.apache.rat; - - import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -41,11 +39,8 @@ import org.apache.commons.io.FileUtils; import org.apache.rat.testhelpers.TextUtils; import org.apache.rat.testhelpers.XmlUtils; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; -import org.w3c.dom.NamedNodeMap; -import org.w3c.dom.Node; import org.w3c.dom.NodeList; public class ReportTest { @@ -55,7 +50,7 @@ public void parseExclusionsForCLIUsage() { .parseExclusions(Arrays.asList("", " # foo/bar", "foo", "##", " ./foo/bar")); assertNotNull(filter); } - + @Test public void testDefaultConfiguration() throws ParseException, IOException { String[] empty = {}; @@ -66,9 +61,9 @@ public void testDefaultConfiguration() throws ParseException, IOException { @Test public void testOutputOption() throws Exception { - CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[]{ "-o", "target/test" }); + CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[] { "-o", "target/test" }); ReportConfiguration config = Report.createConfiguration("target/test-classes/elements", cl); - Reporter.report(config); + new Reporter(config).output(); File output = new File("target/test"); assertTrue(output.exists()); String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); @@ -79,106 +74,107 @@ public void testOutputOption() throws Exception { @Test public void testDefaultOutput() throws Exception { - + File output = new File("target/sysout"); output.delete(); PrintStream origin = System.out; try { System.setOut(new PrintStream(output)); - CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[]{}); + CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[] {}); ReportConfiguration config = Report.createConfiguration("target/test-classes/elements", cl); - Reporter.report(config); + new Reporter(config).output(); } finally { System.setOut(origin); } - assertTrue(output.exists()); - String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); - TextUtils.isMatching("Notes: 2$", content); - TextUtils.isMatching("Binaries: 2$", content); - TextUtils.isMatching("Archives: 1$", content); - TextUtils.isMatching("Standards: 8$", content); - TextUtils.isMatching("Apache Licensed: 5$", content); - TextUtils.isMatching("Generated Documents 1$", content); - TextUtils.isMatching("^2 Unknown licenses", content); - assertTrue(content.contains(" s target/test-classes/elements/ILoggerFactory.java")); - assertTrue(content.contains(" b target/test-classes/elements/Image.png")); - assertTrue(content.contains(" n target/test-classes/elements/LICENSE")); - assertTrue(content.contains(" n target/test-classes/elements/NOTICE")); - assertTrue(content.contains("!s target/test-classes/elements/Source.java")); - assertTrue(content.contains(" s target/test-classes/elements/Text.txt")); - assertTrue(content.contains(" s target/test-classes/elements/TextHttps.txt")); - assertTrue(content.contains(" s target/test-classes/elements/Xml.xml")); - assertTrue(content.contains(" s target/test-classes/elements/buildr.rb")); - assertTrue(content.contains(" a target/test-classes/elements/dummy.jar")); - assertTrue(content.contains(" b target/test-classes/elements/plain.json")); - assertTrue(content.contains("!s target/test-classes/elements/sub/Empty.txt")); - assertTrue(content.contains(" s target/test-classes/elements/tri.txt")); - assertTrue(content.contains(" g target/test-classes/elements/generated.txt")); + assertTrue(output.exists()); + String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); + TextUtils.isMatching("Notes: 2$", content); + TextUtils.isMatching("Binaries: 2$", content); + TextUtils.isMatching("Archives: 1$", content); + TextUtils.isMatching("Standards: 8$", content); + TextUtils.isMatching("Apache Licensed: 5$", content); + TextUtils.isMatching("Generated Documents 1$", content); + TextUtils.isMatching("^2 Unknown licenses", content); + assertTrue(content.contains(" s target/test-classes/elements/ILoggerFactory.java")); + assertTrue(content.contains(" b target/test-classes/elements/Image.png")); + assertTrue(content.contains(" n target/test-classes/elements/LICENSE")); + assertTrue(content.contains(" n target/test-classes/elements/NOTICE")); + assertTrue(content.contains("!s target/test-classes/elements/Source.java")); + assertTrue(content.contains(" s target/test-classes/elements/Text.txt")); + assertTrue(content.contains(" s target/test-classes/elements/TextHttps.txt")); + assertTrue(content.contains(" s target/test-classes/elements/Xml.xml")); + assertTrue(content.contains(" s target/test-classes/elements/buildr.rb")); + assertTrue(content.contains(" a target/test-classes/elements/dummy.jar")); + assertTrue(content.contains(" b target/test-classes/elements/plain.json")); + assertTrue(content.contains("!s target/test-classes/elements/sub/Empty.txt")); + assertTrue(content.contains(" s target/test-classes/elements/tri.txt")); + assertTrue(content.contains(" g target/test-classes/elements/generated.txt")); } - @Test + @Test public void testXMLOutput() throws Exception { - + File output = new File("target/sysout"); output.delete(); PrintStream origin = System.out; try { System.setOut(new PrintStream(output)); - CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[]{"-x"}); + CommandLine cl = new DefaultParser().parse(Report.buildOptions(), new String[] { "-x" }); ReportConfiguration config = Report.createConfiguration("target/test-classes/elements", cl); - Reporter.report(config); + new Reporter(config).output(); } finally { System.setOut(origin); } - assertTrue(output.exists()); - String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); - Document doc = XmlUtils.toDom(new FileInputStream(output)); - XPath xPath = XPathFactory.newInstance().newXPath(); - - NodeList nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@approval='false']"); - assertEquals(2, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='AL']"); - assertEquals(5, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='MIT']"); - assertEquals(1, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='BSD-3']"); - assertEquals(1, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='TMF']"); - assertEquals(1, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='?????']"); - assertEquals(2, nodeList.getLength()); - - // generated, unknown, archive, notice, binary, standard - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='standard']"); - assertEquals(8, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='archive']"); - assertEquals(1, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='binary']"); - assertEquals(2, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='generated']"); - assertEquals(1, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='unknown']"); - assertEquals(0, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='notice']"); - assertEquals(2, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/sample"); - assertEquals(1, nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='generated']/license/notes"); - assertEquals(1,nodeList.getLength()); - - nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@name='target/test-classes/elements/Source.java']/sample"); - assertEquals(1,nodeList.getLength()); + assertTrue(output.exists()); + String content = FileUtils.readFileToString(output, StandardCharsets.UTF_8); + Document doc = XmlUtils.toDom(new FileInputStream(output)); + XPath xPath = XPathFactory.newInstance().newXPath(); + + NodeList nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@approval='false']"); + assertEquals(2, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='AL']"); + assertEquals(5, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='MIT']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='BSD-3']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='TMF']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/license[@id='?????']"); + assertEquals(2, nodeList.getLength()); + + // generated, unknown, archive, notice, binary, standard + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='standard']"); + assertEquals(8, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='archive']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='binary']"); + assertEquals(2, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='generated']"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='unknown']"); + assertEquals(0, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='notice']"); + assertEquals(2, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource/sample"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, "/rat-report/resource[@type='generated']/license/notes"); + assertEquals(1, nodeList.getLength()); + + nodeList = XmlUtils.getNodeList(doc, xPath, + "/rat-report/resource[@name='target/test-classes/elements/Source.java']/sample"); + assertEquals(1, nodeList.getLength()); } } 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 9f8626ad9..d508d581e 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 @@ -24,30 +24,28 @@ import java.io.ByteArrayInputStream; import java.io.ByteArrayOutputStream; import java.io.File; -import java.util.regex.Pattern; import javax.xml.xpath.XPath; import javax.xml.xpath.XPathConstants; import javax.xml.xpath.XPathFactory; import org.apache.commons.io.filefilter.HiddenFileFilter; +import org.apache.rat.api.Document.Type; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.test.utils.Resources; import org.apache.rat.testhelpers.TextUtils; import org.apache.rat.testhelpers.XmlUtils; import org.apache.rat.utils.DefaultLog; import org.apache.rat.walker.DirectoryWalker; -import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.w3c.dom.Document; -import org.w3c.dom.Node; import org.w3c.dom.NodeList; /** * Tests the output of the Reporter. */ public class ReporterTest { - + /** * Finds a node via xpath on the document. And then checks family, approval and * type of elements of the node. @@ -60,21 +58,28 @@ public class ReporterTest { * @param type the type of resource located. * @throws Exception on XPath error. */ - public static void checkNode(Document doc, XPath xpath, String resource, LicenseInfo licenseInfo, String type, boolean hasSample) throws Exception { + public static void checkNode(Document doc, XPath xpath, String resource, LicenseInfo licenseInfo, String type, + boolean hasSample) throws Exception { XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']", resource, type)); if (licenseInfo != null) { - XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s'][@family='%s']",resource, type, licenseInfo.id, licenseInfo.family)); - XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s'][@approval='%s']", resource, type, licenseInfo.id, Boolean.toString(licenseInfo.approval))); + XmlUtils.getNode(doc, xpath, + String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s'][@family='%s']", + resource, type, licenseInfo.id, licenseInfo.family)); + XmlUtils.getNode(doc, xpath, + String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s'][@approval='%s']", + resource, type, licenseInfo.id, Boolean.toString(licenseInfo.approval))); if (licenseInfo.hasNotes) { - XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s']/notes", resource, type, licenseInfo.id)); + XmlUtils.getNode(doc, xpath, + String.format("/rat-report/resource[@name='%s'][@type='%s']/license[@id='%s']/notes", resource, + type, licenseInfo.id)); } } if (hasSample) { - XmlUtils.getNode(doc, xpath, String.format("/rat-report/resource[@name='%s'][@type='%s']/sample", resource, type)); + XmlUtils.getNode(doc, xpath, + String.format("/rat-report/resource[@name='%s'][@type='%s']/sample", resource, type)); } } - @Test public void xmlReportTest() throws Exception { Defaults defaults = Defaults.builder().build(); @@ -86,7 +91,7 @@ public void xmlReportTest() throws Exception { configuration.setFrom(defaults); configuration.setReportable(new DirectoryWalker(new File(elementsPath), HiddenFileFilter.HIDDEN)); configuration.setOut(() -> out); - Reporter.report(configuration); + new Reporter(configuration).output(); Document doc = XmlUtils.toDom(new ByteArrayInputStream(out.toByteArray())); XPath xPath = XPathFactory.newInstance().newXPath(); @@ -94,22 +99,28 @@ public void xmlReportTest() throws Exception { XmlUtils.getNode(doc, xPath, "/rat-report[@timestamp]"); LicenseInfo apacheLic = new LicenseInfo("AL", true, false); - checkNode(doc, xPath, "src/test/resources/elements/ILoggerFactory.java", new LicenseInfo("MIT", true, false), "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/ILoggerFactory.java", new LicenseInfo("MIT", true, false), + "standard", false); checkNode(doc, xPath, "src/test/resources/elements/Image.png", null, "binary", false); checkNode(doc, xPath, "src/test/resources/elements/LICENSE", null, "notice", false); checkNode(doc, xPath, "src/test/resources/elements/NOTICE", null, "notice", false); - checkNode(doc, xPath, "src/test/resources/elements/Source.java", new LicenseInfo("?????", false, false), "standard", true); + checkNode(doc, xPath, "src/test/resources/elements/Source.java", new LicenseInfo("?????", false, false), + "standard", true); checkNode(doc, xPath, "src/test/resources/elements/Text.txt", apacheLic, "standard", false); checkNode(doc, xPath, "src/test/resources/elements/TextHttps.txt", apacheLic, "standard", false); checkNode(doc, xPath, "src/test/resources/elements/Xml.xml", apacheLic, "standard", false); checkNode(doc, xPath, "src/test/resources/elements/buildr.rb", apacheLic, "standard", false); checkNode(doc, xPath, "src/test/resources/elements/dummy.jar", null, "archive", false); checkNode(doc, xPath, "src/test/resources/elements/plain.json", null, "binary", false); - checkNode(doc, xPath, "src/test/resources/elements/sub/Empty.txt", new LicenseInfo("?????", false, false), "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/sub/Empty.txt", new LicenseInfo("?????", false, false), + "standard", false); checkNode(doc, xPath, "src/test/resources/elements/tri.txt", apacheLic, "standard", false); - checkNode(doc, xPath, "src/test/resources/elements/tri.txt", new LicenseInfo("BSD-3", true, false), "standard", false); - checkNode(doc, xPath, "src/test/resources/elements/tri.txt", new LicenseInfo("TMF", "BSD-3", true, false), "standard", false); - checkNode(doc, xPath, "src/test/resources/elements/generated.txt", new LicenseInfo("GEN", true, true), "generated", false); + checkNode(doc, xPath, "src/test/resources/elements/tri.txt", new LicenseInfo("BSD-3", true, false), "standard", + false); + checkNode(doc, xPath, "src/test/resources/elements/tri.txt", new LicenseInfo("TMF", "BSD-3", true, false), + "standard", false); + checkNode(doc, xPath, "src/test/resources/elements/generated.txt", new LicenseInfo("GEN", true, true), + "generated", false); NodeList nodeList = (NodeList) xPath.compile("/rat-report/resource").evaluate(doc, XPathConstants.NODESET); assertEquals(14, nodeList.getLength()); } @@ -121,6 +132,18 @@ public void xmlReportTest() throws Exception { "-------" + NL + // "Generated at: "; + private String documentOut(boolean approved, Type type, String name) { + return String.format("^\\Q%s%s %s\\E$", approved ? " " : "!", type.name().substring(0, 1), name); + } + + private String licenseOut(String family, String name) { + return licenseOut(family, family, name); + } + + private String licenseOut(String family, String id, String name) { + return String.format("\\s+\\Q%s\\E\\s+\\Q%s\\E\\s+\\Q%s\\E$", family, id, name); + } + @Test public void plainReportTest() throws Exception { Defaults defaults = Defaults.builder().build(); @@ -131,12 +154,12 @@ public void plainReportTest() throws Exception { configuration.setFrom(defaults); configuration.setReportable(new DirectoryWalker(new File(elementsPath), HiddenFileFilter.HIDDEN)); configuration.setOut(() -> out); - Reporter.report(configuration); + new Reporter(configuration).output(); out.flush(); String document = out.toString(); - assertTrue(document.startsWith(HEADER), "'Generated at' is not present in " + document ); + assertTrue(document.startsWith(HEADER), "'Generated at' is not present in " + document); TextUtils.assertPatternInOutput("^Notes: 2$", document); TextUtils.assertPatternInOutput("^Binaries: 2$", document); @@ -145,26 +168,40 @@ public void plainReportTest() throws Exception { TextUtils.assertPatternInOutput("^Apache Licensed: 5$", document); TextUtils.assertPatternInOutput("^Generated Documents: 1$", document); TextUtils.assertPatternInOutput("^2 Unknown Licenses$", document); - TextUtils.assertPatternInOutput("^Files with unapproved licenses:\\s+" - + "\\Qsrc/test/resources/elements/Source.java\\E\\s+" - + "\\Qsrc/test/resources/elements/sub/Empty.txt\\E\\s", + TextUtils.assertPatternInOutput( + "^Files with unapproved licenses:\\s+" + "\\Qsrc/test/resources/elements/Source.java\\E\\s+" + + "\\Qsrc/test/resources/elements/sub/Empty.txt\\E\\s", document); - TextUtils.assertPatternInOutput("^ a \\Qsrc/test/resources/elements/dummy.jar\\E", document); - TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/ILoggerFactory.java\\E$\\s+^ MIT The MIT License$", document); - TextUtils.assertPatternInOutput("^ b \\Qsrc/test/resources/elements/Image.png\\E", document); - TextUtils.assertPatternInOutput("^ n \\Qsrc/test/resources/elements/LICENSE\\E", document); - TextUtils.assertPatternInOutput("^ n \\Qsrc/test/resources/elements/NOTICE\\E", document); - TextUtils.assertPatternInOutput("^\\Q!s src/test/resources/elements/Source.java\\E$\\s+^ \\Q?????\\E Unknown license$", document); - TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/Text.txt\\E$\\s+^ AL Apache License Version 2.0$", document); - TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/Xml.xml\\E$\\s+^ AL Apache License Version 2.0$", document); - TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/buildr.rb\\E$\\s+^ AL Apache License Version 2.0$", document); - TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/TextHttps.txt\\E$\\s+^ AL Apache License Version 2.0$", document); - TextUtils.assertPatternInOutput("^ b \\Qsrc/test/resources/elements/plain.json\\E", document); - TextUtils.assertPatternInOutput("^ s \\Qsrc/test/resources/elements/tri.txt\\E$\\s+^ AL Apache License Version 2.0$\\s+ BSD-3 BSD 3 clause$\\s+ TMF The Telemanagement Forum License$", document); - TextUtils.assertPatternInOutput("^\\Q!s src/test/resources/elements/sub/Empty.txt\\E$\\s+^ \\Q?????\\E Unknown license", document); + TextUtils.assertPatternInOutput(documentOut(true, Type.archive, "src/test/resources/elements/dummy.jar"), + document); + TextUtils.assertPatternInOutput( + documentOut(true, Type.standard, "src/test/resources/elements/ILoggerFactory.java") + + licenseOut("MIT", "The MIT License"), + document); + TextUtils.assertPatternInOutput(documentOut(true, Type.binary, "src/test/resources/elements/Image.png"), + document); + TextUtils.assertPatternInOutput(documentOut(true, Type.notice, "src/test/resources/elements/LICENSE"), + document); + TextUtils.assertPatternInOutput(documentOut(true, Type.notice, "src/test/resources/elements/NOTICE"), document); + TextUtils.assertPatternInOutput(documentOut(false, Type.standard, "src/test/resources/elements/Source.java") + + licenseOut("?????", "Unknown license"), document); + TextUtils.assertPatternInOutput(documentOut(true, Type.standard, "src/test/resources/elements/Text.txt") + + licenseOut("AL", "Apache License Version 2.0"), document); + TextUtils.assertPatternInOutput(documentOut(true, Type.standard, "src/test/resources/elements/Xml.xml") + + licenseOut("AL", "Apache License Version 2.0"), document); + TextUtils.assertPatternInOutput(documentOut(true, Type.standard, "src/test/resources/elements/buildr.rb") + + licenseOut("AL", "Apache License Version 2.0"), document); + TextUtils.assertPatternInOutput(documentOut(true, Type.standard, "src/test/resources/elements/TextHttps.txt") + + licenseOut("AL", "Apache License Version 2.0"), document); + TextUtils.assertPatternInOutput(documentOut(true, Type.binary, "src/test/resources/elements/plain.json"), + document); + TextUtils.assertPatternInOutput(documentOut(true, Type.standard, "src/test/resources/elements/tri.txt") + + licenseOut("AL", "Apache License Version 2.0") + licenseOut("BSD-3", "BSD 3 clause") + + licenseOut("BSD-3", "TMF", "The Telemanagement Forum License"), document); + TextUtils.assertPatternInOutput(documentOut(false, Type.standard, "src/test/resources/elements/sub/Empty.txt") + + licenseOut("?????", "Unknown license"), document); } - - + @Test public void UnapprovedLicensesReportTest() throws Exception { Defaults defaults = Defaults.builder().build(); @@ -176,28 +213,27 @@ public void UnapprovedLicensesReportTest() throws Exception { configuration.setReportable(new DirectoryWalker(new File(elementsPath), HiddenFileFilter.HIDDEN)); configuration.setOut(() -> out); configuration.setStyleSheet(this.getClass().getResource("/org/apache/rat/unapproved-licenses.xsl")); - Reporter.report(configuration); + new Reporter(configuration).output(); out.flush(); String document = out.toString(); - assertTrue(document.startsWith("Generated at: "), "'Generated at' is not present in " + document ); + assertTrue(document.startsWith("Generated at: "), "'Generated at' is not present in " + document); TextUtils.assertPatternInOutput("\\Qsrc/test/resources/elements/Source.java\\E$", document); TextUtils.assertPatternInOutput("\\Qsrc/test/resources/elements/sub/Empty.txt\\E", document); } - private class LicenseInfo { String id; String family; boolean approval; boolean hasNotes; - + LicenseInfo(String id, boolean approval, boolean hasNotes) { this(id, id, approval, hasNotes); } - + LicenseInfo(String id, String family, boolean approval, boolean hasNotes) { this.id = id; this.family = ILicenseFamily.makeCategory(family); diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Copyright.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Copyright.java index 034a105e5..4c2b2bba8 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Copyright.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Copyright.java @@ -20,6 +20,7 @@ import org.apache.maven.plugins.annotations.Parameter; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.matchers.CopyrightMatcher; import org.apache.rat.configuration.builders.CopyrightBuilder; public class Copyright extends CopyrightBuilder { @@ -37,7 +38,7 @@ public Copyright() { } @Override - public IHeaderMatcher build() { + public CopyrightMatcher build() { setStart(start).setEnd(stop).setOwner(owner); return super.build(); } diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java index 82c2c8cbe..e2cdb2c52 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/FilesReportable.java @@ -30,6 +30,7 @@ import org.apache.rat.api.MetaData; import org.apache.rat.api.RatException; import org.apache.rat.document.impl.DocumentImplUtils; +import org.apache.rat.document.impl.FileDocument; import org.apache.rat.report.IReportable; import org.apache.rat.report.RatReport; @@ -54,51 +55,9 @@ class FilesReportable implements IReportable { @Override public void run(RatReport report) throws RatException { - FileDocument document = new FileDocument(); + FileDocument document = null; for (String file : files) { - document.setFile(new File(basedir, file)); - document.getMetaData().clear(); - report.report(document); - } - } - - private static class FileDocument implements Document { - private File file; - private final MetaData metaData = new MetaData(); - - void setFile(File file) { - this.file = file; - } - - @Override - public boolean isComposite() { - return DocumentImplUtils.isZip(file); - } - - @Override - public Reader reader() throws IOException { - final InputStream in = Files.newInputStream(file.toPath()); - return new InputStreamReader(in); - } - - @Override - public String getName() { - return DocumentImplUtils.toName(file); - } - - @Override - public MetaData getMetaData() { - return metaData; - } - - @Override - public InputStream inputStream() throws IOException { - return Files.newInputStream(file.toPath()); - } - - @Override - public String toString() { - return "File:" + file.getAbsolutePath(); + report.report(new FileDocument(new File(basedir, file))); } } } 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 e2b9cb610..fad3eb3c2 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 @@ -30,6 +30,7 @@ import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.apache.rat.Defaults; +import org.apache.rat.Report; import org.apache.rat.ReportConfiguration; import org.apache.rat.Reporter; import org.apache.rat.config.AddLicenseHeaders; @@ -98,6 +99,7 @@ public class RatCheckMojo extends AbstractRatMojo { @Parameter(property = "rat.consoleOutput", defaultValue = "true") private boolean consoleOutput; + private Reporter reporter; /** * Invoked by Maven to execute the Mojo. * @@ -120,34 +122,39 @@ public void execute() throws MojoExecutionException, MojoFailureException { } try { - final ClaimStatistic report = Reporter.report(config); - check(report, config); - } catch (MojoExecutionException | MojoFailureException e) { + this.reporter = new Reporter(config); + check(); + } catch (MojoFailureException e) { throw e; } catch (Exception e) { throw new MojoExecutionException(e.getMessage(), e); } } - protected void check(ClaimStatistic statistics, ReportConfiguration config) throws MojoFailureException { + protected void check() throws MojoFailureException { if (numUnapprovedLicenses > 0) { getLog().info("You requested to accept " + numUnapprovedLicenses + " files with unapproved licenses."); } - - int numApproved = statistics.getNumApproved(); - getLog().info("Rat check: Summary over all files. Unapproved: " + statistics.getNumUnApproved() + // - ", unknown: " + statistics.getNumUnknown() + // - ", generated: " + statistics.getNumGenerated() + // - ", approved: " + numApproved + // - (numApproved > 0 ? " licenses." : " license.")); - - if (numUnapprovedLicenses < statistics.getNumUnApproved()) { + ClaimStatistic stats = reporter.getClaimsStatistic(); + + int numApproved = stats.getCounter(ClaimStatistic.Counter.Approved); + StringBuilder statSummary = new StringBuilder("Rat check: Summary over all files. Unapproved: ") + .append(stats.getCounter(ClaimStatistic.Counter.Unapproved)) + .append( ", unknown: ") + .append(stats.getCounter(ClaimStatistic.Counter.Unknown)) + .append(", generated: ") + .append(stats.getCounter(ClaimStatistic.Counter.Generated)) + .append(", approved: ") + .append(numApproved) + .append((numApproved > 0 ? " licenses." : " license.")); + + + getLog().info(statSummary.toString()); + if (numUnapprovedLicenses < stats.getCounter(ClaimStatistic.Counter.Unapproved)) { if (consoleOutput) { try { - config.setStyleSheet(Defaults.getUnapprovedLicensesStyleSheet()); ByteArrayOutputStream baos = new ByteArrayOutputStream(); - config.setOut(()->baos); - Reporter.report(config); + reporter.output(Defaults.getUnapprovedLicensesStyleSheet(), ()->baos); getLog().warn(baos.toString()); } catch (Exception e) { getLog().warn("Unable to print the files with unapproved licenses to the console."); @@ -157,10 +164,10 @@ protected void check(ClaimStatistic statistics, ReportConfiguration config) thro final String seeReport = " See RAT report in: " + reportFile; if (!ignoreErrors) { throw new RatCheckException( - "Too many files with unapproved license: " + statistics.getNumUnApproved() + seeReport); + "Too many files with unapproved license: " + stats.getCounter(ClaimStatistic.Counter.Unapproved) + seeReport); } getLog().warn( - "Rat check: " + statistics.getNumUnApproved() + " files with unapproved licenses." + seeReport); + "Rat check: " + stats.getCounter(ClaimStatistic.Counter.Unapproved) + " files with unapproved licenses." + seeReport); } } 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 7ea35af56..65659561f 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 @@ -406,11 +406,10 @@ protected void executeReport(Locale locale) throws MavenReportException { try { ReportConfiguration config = getConfiguration(); config.setFrom(getDefaultsBuilder().build()); - //config.setStyleSheet(Defaults.getUnapprovedLicensesStyleSheet()); logLicenses(config.getLicenses(LicenseFilter.all)); ByteArrayOutputStream baos = new ByteArrayOutputStream(); config.setOut(()->baos); - Reporter.report(config); + new Reporter(config).output(); sink.text(baos.toString()); } catch (Exception e) { throw new MavenReportException(e.getMessage(), e); diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java index ce3af10dd..3a4bc66b8 100644 --- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java +++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java @@ -19,6 +19,7 @@ package org.apache.rat.anttasks; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.matchers.CopyrightMatcher; import org.apache.rat.configuration.builders.CopyrightBuilder; public class Copyright implements IHeaderMatcher.Builder { @@ -38,7 +39,7 @@ public void setOwner(String owner) { } @Override - public IHeaderMatcher build() { + public CopyrightMatcher build() { return builder.build(); } 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 691d9d6a3..5c373a309 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 @@ -222,7 +222,7 @@ public ReportConfiguration getConfiguration() { @Override public void execute() { try { - Reporter.report(validate(getConfiguration())); + new Reporter(validate(getConfiguration())).output(); } catch (BuildException e) { throw e; } catch (Exception ioex) { diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/ResourceCollectionContainer.java b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/ResourceCollectionContainer.java index 3b24fc739..f487eb3bc 100644 --- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/ResourceCollectionContainer.java +++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/ResourceCollectionContainer.java @@ -47,11 +47,10 @@ class ResourceCollectionContainer implements IReportable { @Override public void run(RatReport report) throws RatException { - ResourceDocument document = new ResourceDocument(); + ResourceDocument document = null; for (Resource r : rc) { if (!r.isDirectory()) { - document.setResource(r); - document.getMetaData().clear(); + document = new ResourceDocument(r); report.report(document); } } @@ -59,11 +58,12 @@ public void run(RatReport report) throws RatException { private static class ResourceDocument implements Document { - private Resource resource; - private final MetaData metaData = new MetaData(); + private final Resource resource; + private final MetaData metaData; - private void setResource(Resource resource) { + private ResourceDocument(Resource resource) { this.resource = resource; + this.metaData = new MetaData(); } @Override diff --git a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java index 26a29838c..8ae1b9b23 100644 --- a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java +++ b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportTest.java @@ -53,16 +53,28 @@ protected File getAntFile() { return antFile; } + private String logLine(String id) { + return logLine(true, getAntFileName(), id); + } + + private String logLine(String antFile, String id) { + return logLine(true, antFile, id); + } + + private String logLine(boolean approved, String antFile, String id) { + return String.format( "%ss \\Q%s\\E\\s+\\Q%s\\E ", approved?" ":"!", antFile, id); + } + @Test public void testWithReportSentToAnt() throws Exception { buildRule.executeTarget("testWithReportSentToAnt"); - assertLogMatches("AL +\\Q" + getAntFileName() + "\\E"); + assertLogMatches(logLine("AL")); } @Test public void testWithReportSentToFile() throws Exception { final File reportFile = new File(getTempDir(), "selftest.report"); - final String alLine = "AL +\\Q" + getAntFileName() + "\\E"; + final String alLine = " s \\Q" + getAntFileName() + "\\E"; if (!getTempDir().mkdirs() && !getTempDir().isDirectory()) { throw new IOException("Could not create temporary directory " + getTempDir()); @@ -79,36 +91,36 @@ public void testWithReportSentToFile() throws Exception { @Test public void testWithALUnknown() throws Exception { buildRule.executeTarget("testWithALUnknown"); - assertLogDoesNotMatch("AL +\\Q" + getAntFileName() + "\\E"); - assertLogMatches("\\!\\?\\?\\?\\?\\? +\\Q" + getAntFileName() + "\\E"); + assertLogDoesNotMatch(logLine("AL")); + assertLogMatches(logLine(false, getAntFileName(), "?????")); } @Test public void testCustomLicense() throws Exception { buildRule.executeTarget("testCustomLicense"); - assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E"); - assertLogMatches(" newFa +\\Q" + getAntFileName() + "\\E"); + assertLogDoesNotMatch(logLine("AL")); + assertLogMatches(logLine("newFa")); } @Test public void testCustomMatcher() throws Exception { buildRule.executeTarget("testCustomMatcher"); - assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E"); - assertLogMatches(" YASL1 +\\Q" + getAntFileName() + "\\E"); + assertLogDoesNotMatch(logLine("AL")); + assertLogMatches(logLine("YASL1")); } @Test public void testInlineCustomMatcher() throws Exception { buildRule.executeTarget("testInlineCustomMatcher"); - assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E"); - assertLogMatches(" YASL1 +\\Q" + getAntFileName() + "\\E"); + assertLogDoesNotMatch(logLine("AL")); + assertLogMatches(logLine("YASL1")); } @Test public void testCustomMatcherBuilder() throws Exception { buildRule.executeTarget("testCustomMatcherBuilder"); - assertLogDoesNotMatch(" AS +\\Q" + getAntFileName() + "\\E"); - assertLogMatches(" YASL1 +\\Q" + getAntFileName() + "\\E"); + assertLogDoesNotMatch(logLine("AL")); + assertLogMatches(logLine("YASL1")); } @Test @@ -127,8 +139,8 @@ public void testCopyrightBuild() throws Exception { try { String fileName = new File(getAntFile().getParent(), "index.apt").getPath().replace('\\', '/'); buildRule.executeTarget("testCopyrightBuild"); - assertLogMatches("YASL1 +\\Q" + fileName + "\\E"); - assertLogDoesNotMatch("AL +\\Q" + fileName + "\\E"); + assertLogMatches(logLine(fileName,"YASL1")); + assertLogDoesNotMatch(logLine(fileName,"AL")); } catch (BuildException e) { final String expect = "You must specify at least one file"; assertTrue("Expected " + expect + ", got " + e.getMessage(), e.getMessage().contains(expect)); diff --git a/apache-rat/src/site/examples/default_output.txt b/apache-rat/src/site/examples/default_output.txt index 65a63a4e0..1bb38511b 100644 --- a/apache-rat/src/site/examples/default_output.txt +++ b/apache-rat/src/site/examples/default_output.txt @@ -2,7 +2,7 @@ ***************************************************** Summary ------- -Generated at: 2024-03-29T15:01:24+01:00 +Generated at: 2024-03-30T14:40:39+01:00 Notes: 2 Binaries: 2 @@ -39,29 +39,43 @@ Files with unapproved licenses: u Unknown file. s src/test/resources/elements/ILoggerFactory.java - MIT The MIT License + MIT MIT The MIT License + b src/test/resources/elements/Image.png + n src/test/resources/elements/LICENSE + n src/test/resources/elements/NOTICE + !s src/test/resources/elements/Source.java - ????? Unknown license + ????? ????? Unknown license + s src/test/resources/elements/Text.txt - AL Apache License Version 2.0 + AL AL Apache License Version 2.0 + s src/test/resources/elements/TextHttps.txt - AL Apache License Version 2.0 + AL AL Apache License Version 2.0 + s src/test/resources/elements/Xml.xml - AL Apache License Version 2.0 + AL AL Apache License Version 2.0 + s src/test/resources/elements/buildr.rb - AL Apache License Version 2.0 + AL AL Apache License Version 2.0 + a src/test/resources/elements/dummy.jar + g src/test/resources/elements/generated.txt - GEN Generated Files + GEN GEN Generated Files + b src/test/resources/elements/plain.json + s src/test/resources/elements/tri.txt - AL Apache License Version 2.0 - BSD-3 BSD 3 clause - TMF The Telemanagement Forum License + AL AL Apache License Version 2.0 + BSD-3 BSD-3 BSD 3 clause + BSD-3 TMF The Telemanagement Forum License + !s src/test/resources/elements/sub/Empty.txt - ????? Unknown license + ????? ????? Unknown license + ***************************************************** From b7df9e9edfbd3e2cac852e261f1323d66b3d00ab Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sat, 30 Mar 2024 16:24:22 +0100 Subject: [PATCH 10/77] added XSDs --- .../resources/org/apache/rat/rat-config.xsd | 163 ++++++++++++++++++ .../resources/org/apache/rat/rat-report.xsd | 29 ++++ 2 files changed, 192 insertions(+) create mode 100644 apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd create mode 100644 apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd diff --git a/apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd b/apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd new file mode 100644 index 000000000..3e5cf5f5d --- /dev/null +++ b/apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd @@ -0,0 +1,163 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file diff --git a/apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd b/apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd new file mode 100644 index 000000000..27aa9694c --- /dev/null +++ b/apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd @@ -0,0 +1,29 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From f6ae778681068ef2d88a849c245e1645810c9af7 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 31 Mar 2024 10:41:42 +0200 Subject: [PATCH 11/77] fixed tests and build issues --- apache-rat-core/pom.xml | 3 +- .../resources/org/apache/rat/rat-config.xsd | 18 +++ .../resources/org/apache/rat/rat-report.xsd | 18 +++ apache-rat-tasks/pom.xml | 4 +- apache-rat-tasks/run-antunit.xml | 11 +- .../org/apache/rat/anttasks/Copyright.java | 2 +- .../java/org/apache/rat/anttasks/Report.java | 4 +- .../antunit/report-bad-configurations.xml | 5 +- .../antunit/report-normal-operation.xml | 138 ++++++++++-------- apache-rat/pom.xml | 2 + 10 files changed, 129 insertions(+), 76 deletions(-) diff --git a/apache-rat-core/pom.xml b/apache-rat-core/pom.xml index 6958dec9e..1b31b093b 100644 --- a/apache-rat-core/pom.xml +++ b/apache-rat-core/pom.xml @@ -25,8 +25,7 @@ apache-rat-core jar Apache Creadur Rat::Core - The core functionality, shared by the Ant tasks - and the Maven plugin. + The core functionality of Rat that is used by all Clients. diff --git a/apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd b/apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd index 3e5cf5f5d..a9f54f758 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd +++ b/apache-rat-core/src/main/resources/org/apache/rat/rat-config.xsd @@ -1,4 +1,22 @@ + diff --git a/apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd b/apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd index 27aa9694c..7061d9258 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd +++ b/apache-rat-core/src/main/resources/org/apache/rat/rat-report.xsd @@ -1,4 +1,22 @@ + diff --git a/apache-rat-tasks/pom.xml b/apache-rat-tasks/pom.xml index 496e8661f..f3339c7f9 100644 --- a/apache-rat-tasks/pom.xml +++ b/apache-rat-tasks/pom.xml @@ -105,7 +105,7 @@ - + diff --git a/apache-rat-tasks/run-antunit.xml b/apache-rat-tasks/run-antunit.xml index e969c1f37..b60c6ec04 100644 --- a/apache-rat-tasks/run-antunit.xml +++ b/apache-rat-tasks/run-antunit.xml @@ -30,11 +30,12 @@ - - - - - + + + + + + diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java index 3a4bc66b8..81954b034 100644 --- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java +++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Copyright.java @@ -39,7 +39,7 @@ public void setOwner(String owner) { } @Override - public CopyrightMatcher build() { + public IHeaderMatcher build() { return builder.build(); } 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 5c373a309..ffc27e2e0 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 @@ -222,7 +222,9 @@ public ReportConfiguration getConfiguration() { @Override public void execute() { try { - new Reporter(validate(getConfiguration())).output(); + Reporter r = new Reporter(validate(getConfiguration())); + r.output(null, ()->System.out); + r.output(); } catch (BuildException e) { throw e; } catch (Exception ioex) { diff --git a/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml b/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml index 1aee502d0..0e49a6f00 100644 --- a/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml +++ b/apache-rat-tasks/src/test/resources/antunit/report-bad-configurations.xml @@ -37,8 +37,7 @@ - + @@ -59,7 +58,7 @@ - + diff --git a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml index 0dee34862..9bf62e6cf 100644 --- a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml +++ b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml @@ -26,6 +26,11 @@ SPDX-License-Identifier: Apache-2.0 xmlns:au="antlib:org.apache.ant.antunit" xmlns:rat="antlib:org.apache.rat.anttasks"> + + + + + + classpath="${test.classpath}" + loaderref="testloader" /> + classpath="${test.classpath}" + loaderref="testloader" /> @@ -66,10 +73,10 @@ SPDX-License-Identifier: Apache-2.0 - + - + @@ -99,7 +106,7 @@ SPDX-License-Identifier: Apache-2.0 - + @@ -107,9 +114,9 @@ SPDX-License-Identifier: Apache-2.0 - + - + @@ -137,8 +144,9 @@ SPDX-License-Identifier: Apache-2.0 - - + + + @@ -155,38 +163,40 @@ SPDX-License-Identifier: Apache-2.0 - - - + + + + + + + + + + + + + + + + - - - - - - - - - - - - - - - - - - - - - - - - - - - + + + + + + + + + + + + @@ -199,21 +209,22 @@ SPDX-License-Identifier: Apache-2.0 - - + + + - - - - - - - - - - - + + + + + + + + + + @@ -359,8 +370,9 @@ SPDX-License-Identifier: Apache-2.0 - - + + + - - + + + - - + + + - - + + + - + diff --git a/apache-rat/pom.xml b/apache-rat/pom.xml index 2dcd8e10a..6054f74ce 100644 --- a/apache-rat/pom.xml +++ b/apache-rat/pom.xml @@ -129,6 +129,8 @@ have no license headers --> README-ANT.txt README-CLI.txt + + src/site/examples/** From 63278a6a2dda1f6e765652f56af91dab5357da2f Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Mon, 1 Apr 2024 13:36:26 +0200 Subject: [PATCH 12/77] Fixed ReportTransformerTest and missing-headers.xsl --- .../org/apache/rat/missing-headers.xsl | 2 +- .../org/apache/rat/ReportTransformerTest.java | 2 +- .../resources/XmlOutputExamples/elements.xml | 45 +++++++++++++++++-- 3 files changed, 43 insertions(+), 6 deletions(-) diff --git a/apache-rat-core/src/main/resources/org/apache/rat/missing-headers.xsl b/apache-rat-core/src/main/resources/org/apache/rat/missing-headers.xsl index a5df2b49e..d75e4e764 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/missing-headers.xsl +++ b/apache-rat-core/src/main/resources/org/apache/rat/missing-headers.xsl @@ -21,7 +21,7 @@ xmlns:xsl="http://www.w3.org/1999/XSL/Transform"> Files with missing headers: - + diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java index 8dc5d24c1..1cfed1fb3 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/ReportTransformerTest.java @@ -55,7 +55,7 @@ public static Stream transformers() { List lst = new ArrayList<>(); lst.add(Arguments.of("plain-rat.xsl", new String[] { "Notes: 2$", "Binaries: 2$", "Archives: 1$", - "Standards: 7$", "Apache Licensed: 4$", "Generated Documents: 0$", "2 Unknown Licenses" })); + "Standards: 8$", "Apache Licensed: 5$", "Generated Documents: 1$", "2 Unknown Licenses" })); lst.add(Arguments.of("unapproved-licenses.xsl", new String[] { "Files with unapproved licenses", "src/test/resources/elements/Source.java", "src/test/resources/elements/sub/Empty.txt" })); lst.add(Arguments.of("missing-headers.xsl", new String[] { "Files with missing headers", diff --git a/apache-rat-core/src/test/resources/XmlOutputExamples/elements.xml b/apache-rat-core/src/test/resources/XmlOutputExamples/elements.xml index 46c13d560..d3e1d7521 100644 --- a/apache-rat-core/src/test/resources/XmlOutputExamples/elements.xml +++ b/apache-rat-core/src/test/resources/XmlOutputExamples/elements.xml @@ -1,5 +1,14 @@ - -package elements; + + + + + + + + + + + - \ No newline at end of file + ]]> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + \ No newline at end of file From e2eb9f62cd354956718edd7bd8dff7b6031b1001 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sat, 20 Jan 2024 16:36:28 +0100 Subject: [PATCH 13/77] initial work started --- .../src/main/java/org/apache/rat/Report.java | 16 ++++++-- .../org/apache/rat/ReportConfiguration.java | 38 +++++++++++++++++++ .../rat/report/ConfigurationReport.java | 14 +++++++ .../claim/util/ClaimReporterMultiplexer.java | 24 +++++++++++- .../rat/report/xml/XmlReportFactory.java | 2 +- .../org/apache/rat/generation-keywords.txt | 2 +- 6 files changed, 90 insertions(+), 6 deletions(-) create mode 100644 apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java 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 bb783d151..f6e03b8d7 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 @@ -115,7 +115,7 @@ public class Report { private static final String LIST_FAMILIES = "list-families"; private static final String LOG_LEVEL = "log-level"; - + private static final String DRY_RUN = "dry-run"; /** * Set unstyled XML output */ @@ -188,6 +188,15 @@ public static void main(String[] args) throws Exception { static ReportConfiguration createConfiguration(String baseDirectory, CommandLine cl) throws IOException { final ReportConfiguration configuration = new ReportConfiguration(DefaultLog.INSTANCE); + configuration.setDryRun(cl.hasOption(DRY_RUN)); + if (cl.hasOption(LIST_FAMILIES)) { + configuration.listFamilies( LicenseFilter.valueOf(cl.getOptionValue(LIST_FAMILIES).toLowerCase())); + } + + if (cl.hasOption(LIST_LICENSES)) { + configuration.listFamilies( LicenseFilter.valueOf(cl.getOptionValue(LIST_LICENSES).toLowerCase())); + } + if (cl.hasOption('o')) { configuration.setOut(new File(cl.getOptionValue('o'))); } @@ -289,7 +298,9 @@ static Options buildOptions() { Arrays.stream(LicenseFilter.values()).map(LicenseFilter::name).collect(Collectors.toList())); Options opts = new Options() - + .addOption(Option.builder().longOpt(DRY_RUN) + .desc("If set do not update the files but generate the reports.") + .build()) .addOption( Option.builder().hasArg(true).longOpt(LIST_FAMILIES) .desc("List the defined license families (default is none). Valid options are: "+licFilterValues+".") @@ -300,7 +311,6 @@ static Options buildOptions() { .build()) .addOption(new Option(HELP, "help", false, "Print help for the RAT command line interface and exit.")); - Option out = new Option("o", "out", true, "Define the output file where to write a report to (default is System.out)."); 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 279516d01..a9c119305 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 @@ -72,6 +72,9 @@ public class ReportConfiguration { private FilenameFilter inputFileFilter; private IOFileFilter directoryFilter; private Log log; + private LicenseFilter listFamilies; + private LicenseFilter listLicenses; + private boolean dryRun; /** @@ -88,6 +91,9 @@ public ReportConfiguration(Log log) { removedLicenseCategories = new TreeSet<>(); directoryFilter = NameBasedHiddenFileFilter.HIDDEN; styleReport = true; + listFamilies = LicenseFilter.none; + listLicenses = LicenseFilter.none; + dryRun = false; } /** @@ -130,6 +136,38 @@ public void licenseDuplicateOption(ReportingSet.Options state) { licenses.setDuplicateOption(state); } + /** + * Set the level of license families that should be output in the XML document. + * @param filter the license families to list. + */ + public void listFamilies(LicenseFilter filter) { + listFamilies = filter; + } + + /** + * Set the level of licenses that should be output in the XML document. + * @param filter the licenses to list. + */ + public void listLicenses(LicenseFilter filter) { + listLicenses = filter; + } + + /** + * Sets the dry run flag. + * @param state the state for the dry run flag. + */ + public void setDryRun(boolean state) { + dryRun = state; + } + + /** + * Returns the state of the dry run flag. + * @return the stae of the dry run flag. + */ + public boolean isDryRun() { + return dryRun; + } + /** * @return The filename filter for the potential input files. */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java new file mode 100644 index 000000000..92ba95bdd --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -0,0 +1,14 @@ +package org.apache.rat.report; + +import org.apache.rat.ReportConfiguration; + +public class ConfigurationReport extends AbstractReport { + + private final ReportConfiguration configuration; + public ConfigurationReport(ReportConfiguration configuration) { + this.configuration = configuration; + } + + + +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java index 572d7b9cb..3e0456070 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java @@ -18,22 +18,31 @@ */ package org.apache.rat.report.claim.util; +import org.apache.commons.lang3.time.DateFormatUtils; import org.apache.rat.api.Document; import org.apache.rat.api.RatException; import org.apache.rat.document.IDocumentAnalyser; import org.apache.rat.document.RatDocumentAnalysisException; import org.apache.rat.report.RatReport; +import org.apache.rat.report.xml.writer.IXmlWriter; +import java.io.IOException; +import java.util.Calendar; import java.util.List; public class ClaimReporterMultiplexer implements RatReport { + private static final String RAT_REPORT = "rat-report"; + private static final String TIMESTAMP = "timestamp"; + private final IDocumentAnalyser analyser; private final List reporters; + final IXmlWriter writer; - public ClaimReporterMultiplexer(final IDocumentAnalyser pAnalyser, final List reporters) { + public ClaimReporterMultiplexer(final IXmlWriter writer, final IDocumentAnalyser pAnalyser, final List reporters) { analyser = pAnalyser; this.reporters = reporters; + this.writer = writer; } public void report(Document document) throws RatException { @@ -50,6 +59,14 @@ public void report(Document document) throws RatException { } public void startReport() throws RatException { + try { + writer.openElement(RAT_REPORT) + .attribute(TIMESTAMP, + DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT + .format(Calendar.getInstance())); + } catch (IOException e) { + throw new RatException("Cannot open start element", e); + } for (RatReport report : reporters) { report.startReport(); } @@ -59,5 +76,10 @@ public void endReport() throws RatException { for (RatReport report : reporters) { report.endReport(); } + try { + writer.closeDocument(); + } catch (IOException e) { + throw new RatException("Cannot close last element", e); + } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java index b88dbff60..b4073a939 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java @@ -55,7 +55,7 @@ public static RatReport createStandardReport(IXmlWriter writer, if (statistic != null) { reporters.add(new ClaimAggregator(statistic)); } - if (configuration.isAddingLicenses()) { + if (configuration.isAddingLicenses() && !configuration.isDryRun()) { reporters.add(new LicenseAddingReport(configuration.getLog(), configuration.getCopyrightMessage(), configuration.isAddingLicensesForced())); } reporters.add(new SimpleXmlClaimReporter(writer)); diff --git a/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt b/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt index f9314a659..17bda1b2d 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt +++ b/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt @@ -23,4 +23,4 @@ Generated by Maven Autogenerated by Thrift DO NOT EDIT THIS FILE - it is machine generated This class was generated by -Generated by javadoc \ No newline at end of file +qGenerated by javadoc \ No newline at end of file From 1694b3df6da72d19c12ca53ee2eff384d0643873 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sat, 20 Jan 2024 23:14:33 +0100 Subject: [PATCH 14/77] first attempt --- .../claim/impl/xml/SimpleXmlClaimReporter.java | 17 ++++++++++++----- .../apache/rat/report/xml/XmlReportFactory.java | 2 +- 2 files changed, 13 insertions(+), 6 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java index dde1ba5a3..cf9481693 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java @@ -33,6 +33,7 @@ import org.apache.rat.report.xml.writer.IXmlWriter; public class SimpleXmlClaimReporter extends AbstractReport { +<<<<<<< HEAD private static final String RAT_REPORT = "rat-report"; private static final String TIMESTAMP = "timestamp"; private static final String RESOURCE = "resource"; @@ -44,6 +45,14 @@ public class SimpleXmlClaimReporter extends AbstractReport { private static final String TYPE = "type"; private static final String ID = "id"; +======= + private static final String LICENSE_APPROVAL_PREDICATE = "license-approval"; + private static final String LICENSE_FAMILY_PREDICATE = "license-family"; + private static final String HEADER_SAMPLE_PREDICATE = "header-sample"; + private static final String HEADER_TYPE_PREDICATE = "header-type"; + private static final String FILE_TYPE_PREDICATE = "type"; + +>>>>>>> 3dc8c4e6 (first attempt) private final IXmlWriter writer; private static final String NAME = "name"; @@ -90,20 +99,18 @@ private void writeHeaderSample(final MetaData metaData) throws IOException, RatE @Override public void startReport() throws RatException { +<<<<<<< HEAD try { writer.openElement(RAT_REPORT).attribute(TIMESTAMP, DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(Calendar.getInstance())); } catch (IOException e) { throw new RatException("Cannot open start element", e); } +======= +>>>>>>> 3dc8c4e6 (first attempt) } @Override public void endReport() throws RatException { - try { - writer.closeDocument(); - } catch (IOException e) { - throw new RatException("Cannot close last element", e); - } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java index b4073a939..fa9bfeeff 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java @@ -66,6 +66,6 @@ public static RatReport createStandardReport(IXmlWriter writer, final IDocumentAnalyser[] analysers = {analyser, policy}; DocumentAnalyserMultiplexer analysisMultiplexer = new DocumentAnalyserMultiplexer(analysers); - return new ClaimReporterMultiplexer(analysisMultiplexer, reporters); + return new ClaimReporterMultiplexer(writer, analysisMultiplexer, reporters); } } From daa862dd5c3fd936ecd2671289ea6a936a3c242e Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 21 Jan 2024 13:22:03 +0100 Subject: [PATCH 15/77] working version --- .../org/apache/rat/ReportConfiguration.java | 8 + .../rat/analysis/LicenseCollection.java | 9 ++ .../apache/rat/analysis/UnknownLicense.java | 2 + .../analysis/matchers/SimpleRegexMatcher.java | 13 ++ .../java/org/apache/rat/api/RatException.java | 4 + .../configuration/MatcherBuilderTracker.java | 9 +- .../configuration/XMLConfigurationReader.java | 28 ++-- .../builders/MatcherRefBuilder.java | 4 +- .../rat/inspector/AbstractInspector.java | 100 ++++++++++++ .../org/apache/rat/inspector/Inspector.java | 45 ++++++ .../apache/rat/inspector/InspectorWalker.java | 31 ++++ .../org/apache/rat/report/AbstractReport.java | 3 + .../rat/report/ConfigurationReport.java | 143 +++++++++++++++++- .../impl/xml/SimpleXmlClaimReporter.java | 12 -- .../claim/util/ClaimReporterMultiplexer.java | 24 +-- .../rat/report/xml/XmlReportFactory.java | 9 +- .../main/resources/org/apache/rat/default.xml | 2 +- .../org/apache/rat/generation-keywords.txt | 2 +- .../rat/report/ConfigurationReportTest.java | 34 +++++ .../apache/rat/report/xml/XmlReportTest.java | 118 +++++++++++++++ 20 files changed, 556 insertions(+), 44 deletions(-) create mode 100644 apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java create mode 100644 apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java create mode 100644 apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java 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 a9c119305..b7dc3c821 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 @@ -144,6 +144,10 @@ public void listFamilies(LicenseFilter filter) { listFamilies = filter; } + public LicenseFilter listFamilies() { + return listFamilies; + } + /** * Set the level of licenses that should be output in the XML document. * @param filter the licenses to list. @@ -152,6 +156,10 @@ public void listLicenses(LicenseFilter filter) { listLicenses = filter; } + public LicenseFilter listLicenses() { + return listFamilies; + } + /** * Sets the dry run flag. * @param state the state for the dry run flag. diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java index 1b674fad0..3226b576e 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java @@ -22,6 +22,8 @@ import java.util.Collections; import org.apache.rat.analysis.matchers.AbstractMatcherContainer; +import org.apache.rat.inspector.AbstractInspector; +import org.apache.rat.inspector.Inspector; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -95,4 +97,11 @@ public String derivedFrom() { public String getName() { return getLicenseFamily().getFamilyName(); } + + @Override + public Inspector getInspector() { + return AbstractInspector.license(this, matchingLicense == null ? null : matchingLicense.getInspector()); + } + + } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java index a7edf752a..f947af81b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java @@ -18,6 +18,8 @@ */ package org.apache.rat.analysis; +import org.apache.rat.inspector.AbstractInspector; +import org.apache.rat.inspector.Inspector; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.ILicenseFamilyBuilder; diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index f7a9ad40c..602deb1db 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -18,7 +18,15 @@ */ package org.apache.rat.analysis.matchers; +import java.util.Arrays; +import java.util.Collection; import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.inspector.AbstractInspector; +import org.apache.rat.inspector.Inspector; +import org.apache.rat.inspector.Inspector.Type; import org.apache.rat.analysis.IHeaders; @@ -50,4 +58,9 @@ public SimpleRegexMatcher(String id, Pattern pattern) { public boolean matches(IHeaders headers) { return pattern.matcher(headers.raw()).find(); } + + @Override + public Inspector getInspector() { + return AbstractInspector.matcher("regex", getId(), Arrays.asList(AbstractInspector.text(pattern.toString()))); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java b/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java index c89d6bd1f..019a21124 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java +++ b/apache-rat-core/src/main/java/org/apache/rat/api/RatException.java @@ -19,6 +19,10 @@ package org.apache.rat.api; public class RatException extends Exception { + + public static RatException asRatException(Exception e) { + return e instanceof RatException ? (RatException) e : new RatException(e); + } private static final long serialVersionUID = 4940711222435919034L; diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java index 447ad82e3..71d435431 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java @@ -19,6 +19,8 @@ package org.apache.rat.configuration; import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.Map; import java.util.Objects; @@ -34,7 +36,7 @@ */ public class MatcherBuilderTracker { - private static MatcherBuilderTracker INSTANCE; + public static MatcherBuilderTracker INSTANCE; private final Map> matcherBuilders; @@ -81,6 +83,11 @@ public static AbstractBuilder getMatcherBuilder(String name) { private MatcherBuilderTracker() { matcherBuilders = new HashMap<>(); } + + + public Collection> getClasses() { + return Collections.unmodifiableCollection(matcherBuilders.values()); + } private void addBuilderImpl(String className, String name) { Objects.requireNonNull(className, "className may not be null"); 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 b05711b07..eb23dec2b 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 @@ -83,21 +83,21 @@ public class XMLConfigurationReader implements LicenseReader, MatcherReader { - private final static String ATT_ID = "id"; - private final static String ATT_NAME = "name"; + public final static String ATT_ID = "id"; + public final static String ATT_NAME = "name"; private final static String ATT_DERIVED_FROM = "derived_from"; - private final static String ATT_LICENSE_REF = "license_ref"; - private final static String ATT_CLASS_NAME = "class"; - - private final static String ROOT = "rat-config"; - private final static String FAMILIES = "families"; - private final static String LICENSES = "licenses"; - private final static String LICENSE = "license"; - private final static String APPROVED = "approved"; - private final static String FAMILY = "family"; - private final static String NOTE = "note"; - private final static String MATCHERS = "matchers"; - private final static String MATCHER = "matcher"; + public final static String ATT_LICENSE_REF = "license_ref"; + public final static String ATT_CLASS_NAME = "class"; + + public final static String ROOT = "rat-config"; + public final static String FAMILIES = "families"; + public final static String LICENSES = "licenses"; + public final static String LICENSE = "license"; + public final static String APPROVED = "approved"; + public final static String FAMILY = "family"; + public final static String NOTE = "note"; + public final static String MATCHERS = "matchers"; + public final static String MATCHER = "matcher"; private Document document; private final Element rootElement; diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java index 3c047bc58..5e46d67a8 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java @@ -18,6 +18,8 @@ */ package org.apache.rat.configuration.builders; +import java.util.Arrays; +import java.util.Collection; import java.util.Map; import org.apache.rat.analysis.IHeaderMatcher; @@ -34,6 +36,7 @@ public class MatcherRefBuilder extends AbstractBuilder { private String referenceId; private Map matchers; + public static final String ATT_REF_ID = "refId"; /** * Constructs the MatcherReferenceBuilder using the provided reference id. @@ -110,5 +113,4 @@ public boolean matches(IHeaders headers) { return wrapped.matches(headers); } } - } diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java new file mode 100644 index 000000000..e5be4e5fc --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java @@ -0,0 +1,100 @@ +package org.apache.rat.inspector; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.List; + +import org.apache.rat.license.ILicense; + +public abstract class AbstractInspector implements Inspector { + private final Type type; + private final String name; + + public AbstractInspector(Type type, String name) { + this.type = type; + this.name = name; + } + + @Override + public Type getType() { + return type; + } + + @Override + public String getCommonName() { + return name; + } + + public static Inspector license(ILicense license, Inspector matcher) { + return new AbstractInspector(Inspector.Type.License, "license") { + + @Override + public Collection getChildren() { + List result = new ArrayList<>(); + if (!license.getName().equals(license.getLicenseFamily().getFamilyName())) { + result.add(parameter("name", license.getName())); + } + if (!license.getId().equals(license.getLicenseFamily().getFamilyCategory().trim())) { + result.add(parameter("id", license.getId())); + } + result.add(parameter("family", license.getLicenseFamily().getFamilyCategory().trim())); + result.add(parameter("notes", license.getNotes())); + if (matcher != null) { + result.add(matcher); + } + return result; + } + }; + } + + public static Inspector parameter(String name, String value) { + return new Inspector() { + @Override + public Inspector.Type getType() { + return Inspector.Type.Parameter; + } + + @Override + public String getCommonName() { + return name; + } + + @Override + public String getParamValue() { + return value == null ? "" : value; + } + }; + } + + public static Inspector text(String value) { + return new Inspector() { + @Override + public Inspector.Type getType() { + return Inspector.Type.Text; + } + + @Override + public String getCommonName() { + return ""; + } + + @Override + public String getParamValue() { + return value == null ? "" : value; + } + }; + } + + public static Inspector matcher(String name, String id, Collection children) { + return new AbstractInspector(Type.Matcher, name) { + @Override + public Collection getChildren() { + List result = new ArrayList<>(); + result.add(parameter("id", id)); + result.addAll(children); + return result; + } + }; + } + +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java new file mode 100644 index 000000000..f11cec476 --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java @@ -0,0 +1,45 @@ +package org.apache.rat.inspector; + +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + + +/** + * An interface that explains what the matcher operates on. + */ +public interface Inspector { + + public enum Type { License, Matcher, Parameter, Text }; + + public Type getType(); + + /** + * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) + * @return + */ + String getCommonName(); + + /** + * Gets the string parameter value if this inspector has no + * @return the string value (default returns an empty string. + */ + default String getParamValue() { return ""; } + + /** + * Gets a map of the parameters that the object contains. For example Copyright has 'start', 'stop', and 'owner' + * parameters. Some IHeaderMatchers have simple text values (e.g. 'regex' or 'text' types) these should list + * an unnamed parameter (empty string) with the text value. + * @return the map of parameters to the objects that represent them. + */ + default Collection getChildren() { return Collections.emptyList(); } + + /** + * Get all the children of a specific type + * @param type the type to return + * @return the colleciton of children of the specified type. + */ + default Collection childrenOfType(Type type) { + return getChildren().stream().filter(i -> i.getType() == type).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java new file mode 100644 index 000000000..a558aee1f --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java @@ -0,0 +1,31 @@ +package org.apache.rat.inspector; + +import java.util.Arrays; + +import org.apache.commons.lang3.StringUtils; + +public class InspectorWalker { + + private Inspector inspector; + + public InspectorWalker(Inspector inspector) { + this.inspector = inspector; + } + + public String toString() { + return dump(0,2,inspector); + } + + private String dump(int indent, int indentIncr, Inspector inspector) { + String padding = StringUtils.repeat(' ', indent); + StringBuilder sb = new StringBuilder(); + sb.append(padding).append( inspector.getCommonName() ); + if (StringUtils.isNotBlank(inspector.getParamValue())) { + sb.append( ": ").append( inspector.getParamValue()); + } + sb.append( StringUtils.CR ); + inspector.getChildren().forEach( s -> sb.append( dump(indent+indentIncr, indentIncr, s))); + return sb.toString(); + } + +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java index d3d896e90..3e5258375 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java @@ -18,6 +18,8 @@ */ package org.apache.rat.report; +import java.io.IOException; + import org.apache.rat.api.Document; import org.apache.rat.api.RatException; @@ -28,6 +30,7 @@ public abstract class AbstractReport implements RatReport { /** * Empty default implementation. + * @throws IOException */ public void startReport() throws RatException { // Does nothing diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java index 92ba95bdd..22b9c90fc 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -1,14 +1,151 @@ package org.apache.rat.report; +import java.io.IOException; +import java.util.Collection; +import java.util.HashSet; +import java.util.Optional; +import java.util.Set; +import java.util.SortedSet; +import java.util.UUID; + import org.apache.rat.ReportConfiguration; +import org.apache.rat.api.RatException; +import org.apache.rat.configuration.MatcherBuilderTracker; +import org.apache.rat.configuration.XMLConfigurationReader; +import org.apache.rat.configuration.builders.MatcherRefBuilder; +import org.apache.rat.inspector.Inspector; +import org.apache.rat.inspector.Inspector.Type; +import org.apache.rat.license.ILicense; +import org.apache.rat.license.ILicenseFamily; +import org.apache.rat.license.LicenseSetFactory.LicenseFilter; +import org.apache.rat.report.xml.writer.IXmlWriter; public class ConfigurationReport extends AbstractReport { private final ReportConfiguration configuration; - public ConfigurationReport(ReportConfiguration configuration) { + private final IXmlWriter writer; + private final Set matchers; + + public ConfigurationReport(IXmlWriter writer, ReportConfiguration configuration) { this.configuration = configuration; + this.writer = writer; + this.matchers = new HashSet<>(); + } + + @Override + public void startReport() throws RatException { + if (configuration.listFamilies() != LicenseFilter.none || configuration.listLicenses() != LicenseFilter.none) { + try { + writer.openElement(XMLConfigurationReader.ROOT); + + // write Families section + SortedSet families = configuration.getLicenseFamilies(configuration.listFamilies()); + if (!families.isEmpty()) { + writer.openElement(XMLConfigurationReader.FAMILIES); + for (ILicenseFamily family : families) { + writeFamily(family); + } + writer.closeElement(); // FAMILIES + } + + // write licenses section + SortedSet licenses = configuration.getLicenses(configuration.listLicenses()); + if (!licenses.isEmpty()) { + writer.openElement(XMLConfigurationReader.LICENSES); + for (ILicense license : licenses) { + writeInspector(license.getInspector()); + } + writer.closeElement();// LICENSES + } + + // write approved section + writer.openElement(XMLConfigurationReader.APPROVED); + for (String family : configuration.getApprovedLicenseCategories()) { + writer.openElement(XMLConfigurationReader.APPROVED) + .attribute(XMLConfigurationReader.ATT_LICENSE_REF, family.trim()).closeElement(); + } + writer.closeElement(); // APPROVED + + // write matchers section + MatcherBuilderTracker tracker = MatcherBuilderTracker.INSTANCE; + writer.openElement(XMLConfigurationReader.MATCHERS); + for (Class clazz : tracker.getClasses()) { + writer.openElement(XMLConfigurationReader.MATCHER) + .attribute(XMLConfigurationReader.ATT_CLASS_NAME, clazz.getCanonicalName()).closeElement(); + } + writer.closeElement(); // MATCHERS + + writer.closeElement(); // ROOT + } catch (IOException e) { + throw new RatException(e); + } + } + } + + private void writeFamily(ILicenseFamily family) throws RatException { + try { + writer.openElement(XMLConfigurationReader.FAMILY) + .attribute(XMLConfigurationReader.ATT_ID, family.getFamilyCategory().trim()) + .attribute(XMLConfigurationReader.ATT_NAME, family.getFamilyName()); + writer.closeElement(); + } catch (IOException e) { + throw new RatException(e); + } + } + + private void writeInspectors(Collection inspectors) throws RatException { + for (Inspector inspector : inspectors) { + writeInspector(inspector); + } + } + + private void writeInspector(Inspector inspector) throws RatException { + if (inspector == null) { + return; + } + try { + switch (inspector.getType()) { + case Matcher: + // see if id was registered + Optional id = inspector.getChildren().stream().filter( + i -> i.getType() == Type.Parameter && i.getCommonName().equals(XMLConfigurationReader.ATT_ID)) + .findFirst(); + if (id.isPresent()) { + String idStr = id.get().getParamValue(); + if (matchers.contains(idStr)) { + writer.openElement("matcherRef").attribute(MatcherRefBuilder.ATT_REF_ID, idStr).closeElement(); + return; + } + matchers.add(idStr); + } + writer.openElement(inspector.getCommonName()); + writeInspectors(inspector.getChildren()); + writer.closeElement(); + break; + case License: + writer.openElement(XMLConfigurationReader.LICENSE); + writeInspectors(inspector.getChildren()); + writer.closeElement(); + break; + case Parameter: + if (inspector.getCommonName().equals("id")) { + try { + // if a UUID skip it. + UUID.fromString(inspector.getParamValue()); + return; + } catch (IllegalArgumentException expected) { + // do nothing. + } + } + writer.attribute(inspector.getCommonName(), inspector.getParamValue()); + break; + case Text: + writer.content(inspector.getParamValue()); + break; + } + } catch (IOException e) { + throw new RatException(e); + } } - - } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java index cf9481693..8c2942193 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/impl/xml/SimpleXmlClaimReporter.java @@ -33,7 +33,6 @@ import org.apache.rat.report.xml.writer.IXmlWriter; public class SimpleXmlClaimReporter extends AbstractReport { -<<<<<<< HEAD private static final String RAT_REPORT = "rat-report"; private static final String TIMESTAMP = "timestamp"; private static final String RESOURCE = "resource"; @@ -45,14 +44,6 @@ public class SimpleXmlClaimReporter extends AbstractReport { private static final String TYPE = "type"; private static final String ID = "id"; -======= - private static final String LICENSE_APPROVAL_PREDICATE = "license-approval"; - private static final String LICENSE_FAMILY_PREDICATE = "license-family"; - private static final String HEADER_SAMPLE_PREDICATE = "header-sample"; - private static final String HEADER_TYPE_PREDICATE = "header-type"; - private static final String FILE_TYPE_PREDICATE = "type"; - ->>>>>>> 3dc8c4e6 (first attempt) private final IXmlWriter writer; private static final String NAME = "name"; @@ -99,15 +90,12 @@ private void writeHeaderSample(final MetaData metaData) throws IOException, RatE @Override public void startReport() throws RatException { -<<<<<<< HEAD try { writer.openElement(RAT_REPORT).attribute(TIMESTAMP, DateFormatUtils.ISO_8601_EXTENDED_DATETIME_TIME_ZONE_FORMAT.format(Calendar.getInstance())); } catch (IOException e) { throw new RatException("Cannot open start element", e); } -======= ->>>>>>> 3dc8c4e6 (first attempt) } @Override diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java index 3e0456070..c76e8b357 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java @@ -37,25 +37,29 @@ public class ClaimReporterMultiplexer implements RatReport { private final IDocumentAnalyser analyser; private final List reporters; - final IXmlWriter writer; + private final IXmlWriter writer; + private final boolean dryRun; - public ClaimReporterMultiplexer(final IXmlWriter writer, final IDocumentAnalyser pAnalyser, final List reporters) { + public ClaimReporterMultiplexer(final boolean dryRun, final IXmlWriter writer, final IDocumentAnalyser pAnalyser, final List reporters) { analyser = pAnalyser; this.reporters = reporters; this.writer = writer; + this.dryRun = dryRun; } public void report(Document document) throws RatException { - if (analyser != null) { - try { - analyser.analyse(document); - } catch (RatDocumentAnalysisException e) { - throw new RatException(e.getMessage(), e); + if (!dryRun) { + if (analyser != null) { + try { + analyser.analyse(document); + } catch (RatDocumentAnalysisException e) { + throw new RatException(e.getMessage(), e); + } } + for (RatReport report : reporters) { + report.report(document); + } } - for (RatReport report : reporters) { - report.report(document); - } } public void startReport() throws RatException { diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java index fa9bfeeff..8c76dc2ce 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/XmlReportFactory.java @@ -24,6 +24,7 @@ import org.apache.rat.document.impl.util.DocumentAnalyserMultiplexer; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; import org.apache.rat.policy.DefaultPolicy; +import org.apache.rat.report.ConfigurationReport; import org.apache.rat.report.RatReport; import org.apache.rat.report.claim.ClaimStatistic; import org.apache.rat.report.claim.impl.ClaimAggregator; @@ -58,6 +59,12 @@ public static RatReport createStandardReport(IXmlWriter writer, if (configuration.isAddingLicenses() && !configuration.isDryRun()) { reporters.add(new LicenseAddingReport(configuration.getLog(), configuration.getCopyrightMessage(), configuration.isAddingLicensesForced())); } + + if (configuration.listFamilies() != LicenseFilter.none || configuration.listLicenses() != LicenseFilter.none) { + + reporters.add(new ConfigurationReport(writer, configuration)); + } + reporters.add(new SimpleXmlClaimReporter(writer)); final IDocumentAnalyser analyser = @@ -66,6 +73,6 @@ public static RatReport createStandardReport(IXmlWriter writer, final IDocumentAnalyser[] analysers = {analyser, policy}; DocumentAnalyserMultiplexer analysisMultiplexer = new DocumentAnalyserMultiplexer(analysers); - return new ClaimReporterMultiplexer(writer, analysisMultiplexer, reporters); + return new ClaimReporterMultiplexer(configuration.isDryRun(), writer, analysisMultiplexer, reporters); } } diff --git a/apache-rat-core/src/main/resources/org/apache/rat/default.xml b/apache-rat-core/src/main/resources/org/apache/rat/default.xml index db2fb2b3d..0fbb53440 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/default.xml +++ b/apache-rat-core/src/main/resources/org/apache/rat/default.xml @@ -157,7 +157,7 @@ may be prepared copied published and distributed + owner="OASIS Open"/> diff --git a/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt b/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt index 17bda1b2d..f9314a659 100644 --- a/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt +++ b/apache-rat-core/src/main/resources/org/apache/rat/generation-keywords.txt @@ -23,4 +23,4 @@ Generated by Maven Autogenerated by Thrift DO NOT EDIT THIS FILE - it is machine generated This class was generated by -qGenerated by javadoc \ No newline at end of file +Generated by javadoc \ No newline at end of file diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java new file mode 100644 index 000000000..8fab1d93d --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java @@ -0,0 +1,34 @@ +package org.apache.rat.report; + +import java.io.IOException; +import java.io.StringWriter; + +import org.apache.rat.report.xml.writer.impl.base.XmlWriter; +import org.apache.rat.report.xml.writer.IXmlWriter; +import org.apache.rat.Defaults; +import org.apache.rat.ReportConfiguration; +import org.apache.rat.api.RatException; +import org.apache.rat.license.LicenseSetFactory.LicenseFilter; +import org.apache.rat.utils.DefaultLog; +import org.junit.jupiter.api.Test; + +public class ConfigurationReportTest { + + + @Test + public void testAll() throws RatException, IOException { + ReportConfiguration reportConfiguration = new ReportConfiguration(DefaultLog.INSTANCE); + reportConfiguration.setFrom(Defaults.builder().build()); + reportConfiguration.listFamilies(LicenseFilter.all); + reportConfiguration.listLicenses(LicenseFilter.all); + StringWriter sw = new StringWriter(); + IXmlWriter writer = new XmlWriter(sw); + + ConfigurationReport report = new ConfigurationReport(writer, reportConfiguration); + report.startReport(); + report.endReport(); + writer.closeDocument(); + System.out.println( sw ); + + } +} diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java new file mode 100644 index 000000000..e1773c844 --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/report/xml/XmlReportTest.java @@ -0,0 +1,118 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + */ +package org.apache.rat.report.xml; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.BufferedWriter; +import java.io.ByteArrayInputStream; +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.OutputStreamWriter; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; + +import javax.xml.xpath.XPath; +import javax.xml.xpath.XPathFactory; + +import org.apache.commons.io.filefilter.HiddenFileFilter; +import org.apache.rat.analysis.DefaultAnalyserFactory; +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.matchers.CopyrightMatcher; +import org.apache.rat.analysis.matchers.OrMatcher; +import org.apache.rat.analysis.matchers.SimpleTextMatcher; +import org.apache.rat.document.IDocumentAnalyser; +import org.apache.rat.license.ILicense; +import org.apache.rat.report.AbstractReport; +import org.apache.rat.report.RatReport; +import org.apache.rat.report.claim.impl.xml.SimpleXmlClaimReporter; +import org.apache.rat.report.claim.util.ClaimReporterMultiplexer; +import org.apache.rat.report.xml.writer.IXmlWriter; +import org.apache.rat.report.xml.writer.impl.base.XmlWriter; +import org.apache.rat.test.utils.Resources; +import org.apache.rat.testhelpers.TestingLicense; +import org.apache.rat.testhelpers.XmlUtils; +import org.apache.rat.utils.DefaultLog; +import org.apache.rat.walker.DirectoryWalker; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; +import org.w3c.dom.Document; + +public class XmlReportTest { + + private static final Pattern IGNORE = Pattern.compile(".svn"); + private ByteArrayOutputStream out; + private IXmlWriter writer; + private RatReport report; + + @BeforeEach + public void setUp() throws Exception { + out = new ByteArrayOutputStream(); + writer = new XmlWriter(new BufferedWriter(new OutputStreamWriter(out))); + writer.startDocument(); + final SimpleXmlClaimReporter reporter = new SimpleXmlClaimReporter(writer); + final IHeaderMatcher asf1Matcher = new SimpleTextMatcher("http://www.apache.org/licenses/LICENSE-2.0"); + final IHeaderMatcher asf2Matcher = new SimpleTextMatcher("https://www.apache.org/licenses/LICENSE-2.0.txt"); + final IHeaderMatcher asfMatcher = new OrMatcher(Arrays.asList(asf1Matcher, asf2Matcher)); + final ILicense asfLic = new TestingLicense("ASF", asfMatcher); + + final IHeaderMatcher qosMatcher = new CopyrightMatcher("2004", "2011", "QOS.ch"); + final ILicense qosLic = new TestingLicense("QOS", qosMatcher); + + IDocumentAnalyser analyser = DefaultAnalyserFactory.createDefaultAnalyser(DefaultLog.INSTANCE,Arrays.asList(asfLic, qosLic)); + final List reporters = new ArrayList<>(); + reporters.add(reporter); + report = new ClaimReporterMultiplexer(false, writer, analyser, reporters); + } + + private void report(DirectoryWalker directory) throws Exception { + directory.run(report); + } + + @Test + public void baseReport() throws Exception { + final String elementsPath = Resources.getResourceDirectory("elements/Source.java"); + DirectoryWalker directory = new DirectoryWalker(new File(elementsPath), IGNORE, HiddenFileFilter.HIDDEN); + report.startReport(); + report(directory); + report.endReport(); + writer.closeDocument(); + final String output = out.toString(); + assertTrue(output.startsWith("" + " Date: Sun, 21 Jan 2024 13:46:13 +0100 Subject: [PATCH 16/77] added ASF licenses and cleaned up code --- .../org/apache/rat/ReportConfiguration.java | 2 +- .../matchers/AbstractHeaderMatcher.java | 7 +++-- .../matchers/AbstractMatcherContainer.java | 23 ++++++++------ .../analysis/matchers/SimpleRegexMatcher.java | 20 ++++++------ .../rat/inspector/AbstractInspector.java | 22 ++++++++++++- .../org/apache/rat/inspector/Inspector.java | 18 +++++++++++ .../apache/rat/inspector/InspectorWalker.java | 31 ------------------- .../rat/report/ConfigurationReport.java | 18 +++++++++++ .../claim/util/ClaimReporterMultiplexer.java | 3 ++ .../rat/report/ConfigurationReportTest.java | 22 +++++++++++-- .../src/test/java/org/example/Matcher.java | 7 +++++ 11 files changed, 117 insertions(+), 56 deletions(-) delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java 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 b7dc3c821..fd5e3d7b3 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 @@ -157,7 +157,7 @@ public void listLicenses(LicenseFilter filter) { } public LicenseFilter listLicenses() { - return listFamilies; + return listLicenses; } /** diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java index 64e2cc696..f3123ee32 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java @@ -24,14 +24,17 @@ import org.apache.rat.analysis.IHeaderMatcher; /** - * An abstract class to simplify IHeaderMatcher creation. This class ensures that the id is set. + * An abstract class to simplify IHeaderMatcher creation. This class ensures + * that the id is set. */ public abstract class AbstractHeaderMatcher implements IHeaderMatcher { private final String id; /** - * Constructs the IHeaderMatcher with an id value. If {@code id} is null then a unique random id is created. + * Constructs the IHeaderMatcher with an id value. If {@code id} is null then a + * unique random id is created. + * * @param id the Id to use. */ protected AbstractHeaderMatcher(String id) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java index 466629520..e03d69a84 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java @@ -25,19 +25,21 @@ import org.apache.rat.analysis.IHeaderMatcher; /** - * A class that implements IHeaderMatcher as a collection of other IHeaderMatchers. + * A class that implements IHeaderMatcher as a collection of other + * IHeaderMatchers. */ public abstract class AbstractMatcherContainer extends AbstractHeaderMatcher { protected final Collection enclosed; /** - * Constructs the abstract matcher container. - * If the {@code id} is not set then a unique random identifier is created. - * The {@code enclosed} collection is preserved in a new collection that retains the order of - * of the original collection. + * Constructs the abstract matcher container. If the {@code id} is not set then + * a unique random identifier is created. The {@code enclosed} collection is + * preserved in a new collection that retains the order of of the original + * collection. + * * @param id The id for the matcher. - * @param enclosed the collection of enclosed matchers. + * @param enclosed the collection of enclosed matchers. */ public AbstractMatcherContainer(String id, Collection enclosed) { super(id); @@ -46,10 +48,11 @@ public AbstractMatcherContainer(String id, Collection } /** - * Constructs the abstract matcher container with a unique random id. - * The {@code enclosed} collection is preserved in a new collection that retains the order of - * of the original collection. - * @param enclosed the collection of enclosed matchers. + * Constructs the abstract matcher container with a unique random id. The + * {@code enclosed} collection is preserved in a new collection that retains the + * order of of the original collection. + * + * @param enclosed the collection of enclosed matchers. */ public AbstractMatcherContainer(Collection enclosed) { this(null, enclosed); diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index 602deb1db..83b75a7fb 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -19,14 +19,10 @@ package org.apache.rat.analysis.matchers; import java.util.Arrays; -import java.util.Collection; import java.util.regex.Pattern; -import java.util.stream.Collectors; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.inspector.AbstractInspector; import org.apache.rat.inspector.Inspector; -import org.apache.rat.inspector.Inspector.Type; import org.apache.rat.analysis.IHeaders; @@ -37,17 +33,23 @@ public class SimpleRegexMatcher extends AbstractSimpleMatcher { private final Pattern pattern; /** - * Constructs a regex pattern matcher with a unique random id and the specified Regex pattern. - * @param pattern the pattern to match. Pattern will only match a single line from the input stream. + * Constructs a regex pattern matcher with a unique random id and the specified + * Regex pattern. + * + * @param pattern the pattern to match. Pattern will only match a single line + * from the input stream. */ public SimpleRegexMatcher(Pattern pattern) { this(null, pattern); } /** - * Constructs a regex pattern matcher with a unique random id and the specified Regex pattern. + * Constructs a regex pattern matcher with a unique random id and the specified + * Regex pattern. + * * @param id the id for this matcher - * @param pattern the pattern to match. Pattern will only match a single line from the input stream. + * @param pattern the pattern to match. Pattern will only match a single line + * from the input stream. */ public SimpleRegexMatcher(String id, Pattern pattern) { super(id); @@ -58,7 +60,7 @@ public SimpleRegexMatcher(String id, Pattern pattern) { public boolean matches(IHeaders headers) { return pattern.matcher(headers.raw()).find(); } - + @Override public Inspector getInspector() { return AbstractInspector.matcher("regex", getId(), Arrays.asList(AbstractInspector.text(pattern.toString()))); diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java index e5be4e5fc..8b1525575 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java +++ b/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + */ package org.apache.rat.inspector; import java.util.ArrayList; @@ -91,7 +109,9 @@ public static Inspector matcher(String name, String id, Collection ch public Collection getChildren() { List result = new ArrayList<>(); result.add(parameter("id", id)); - result.addAll(children); + if (children != null) { + result.addAll(children); + } return result; } }; diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java index f11cec476..346513f0b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java +++ b/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + */ package org.apache.rat.inspector; import java.util.Collection; diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java deleted file mode 100644 index a558aee1f..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/inspector/InspectorWalker.java +++ /dev/null @@ -1,31 +0,0 @@ -package org.apache.rat.inspector; - -import java.util.Arrays; - -import org.apache.commons.lang3.StringUtils; - -public class InspectorWalker { - - private Inspector inspector; - - public InspectorWalker(Inspector inspector) { - this.inspector = inspector; - } - - public String toString() { - return dump(0,2,inspector); - } - - private String dump(int indent, int indentIncr, Inspector inspector) { - String padding = StringUtils.repeat(' ', indent); - StringBuilder sb = new StringBuilder(); - sb.append(padding).append( inspector.getCommonName() ); - if (StringUtils.isNotBlank(inspector.getParamValue())) { - sb.append( ": ").append( inspector.getParamValue()); - } - sb.append( StringUtils.CR ); - inspector.getChildren().forEach( s -> sb.append( dump(indent+indentIncr, indentIncr, s))); - return sb.toString(); - } - -} diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java index 22b9c90fc..799f2b307 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + */ package org.apache.rat.report; import java.io.IOException; diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java index c76e8b357..0e85347c7 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/claim/util/ClaimReporterMultiplexer.java @@ -47,6 +47,7 @@ public ClaimReporterMultiplexer(final boolean dryRun, final IXmlWriter writer, f this.dryRun = dryRun; } + @Override public void report(Document document) throws RatException { if (!dryRun) { if (analyser != null) { @@ -62,6 +63,7 @@ public void report(Document document) throws RatException { } } + @Override public void startReport() throws RatException { try { writer.openElement(RAT_REPORT) @@ -76,6 +78,7 @@ public void startReport() throws RatException { } } + @Override public void endReport() throws RatException { for (RatReport report : reporters) { report.endReport(); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java index 8fab1d93d..b3ac3111f 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one * + * or more contributor license agreements. See the NOTICE file * + * distributed with this work for additional information * + * regarding copyright ownership. The ASF licenses this file * + * to you under the Apache License, Version 2.0 (the * + * "License"); you may not use this file except in compliance * + * with the License. You may obtain a copy of the License at * + * * + * http://www.apache.org/licenses/LICENSE-2.0 * + * * + * Unless required by applicable law or agreed to in writing, * + * software distributed under the License is distributed on an * + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * + * KIND, either express or implied. See the License for the * + * specific language governing permissions and limitations * + * under the License. * + */ package org.apache.rat.report; import java.io.IOException; @@ -28,7 +46,7 @@ public void testAll() throws RatException, IOException { report.startReport(); report.endReport(); writer.closeDocument(); - System.out.println( sw ); - + String result = sw.toString(); + // AssertTrue( result.contains( "")); } } diff --git a/apache-rat-tasks/src/test/java/org/example/Matcher.java b/apache-rat-tasks/src/test/java/org/example/Matcher.java index 26504091b..392f42321 100644 --- a/apache-rat-tasks/src/test/java/org/example/Matcher.java +++ b/apache-rat-tasks/src/test/java/org/example/Matcher.java @@ -18,6 +18,8 @@ import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.matchers.AbstractSimpleMatcher; +import org.apache.rat.inspector.AbstractInspector; +import org.apache.rat.inspector.Inspector; public class Matcher extends AbstractSimpleMatcher { public Matcher() { @@ -29,4 +31,9 @@ public boolean matches(IHeaders headers) { return true; } + @Override + public Inspector getInspector() { + return AbstractInspector.matcher("MyCustomMatcher", getId(), null); + } + } From 98f46901190f0adb04369e6848533b8b947478fd Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 21 Jan 2024 14:18:39 +0100 Subject: [PATCH 17/77] updated ant tasks to match requierments --- .../src/test/resources/antunit/report-normal-operation.xml | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml index 9bf62e6cf..9f3f4c5d7 100644 --- a/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml +++ b/apache-rat-tasks/src/test/resources/antunit/report-normal-operation.xml @@ -469,6 +469,8 @@ package org.example; import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.matchers.AbstractSimpleMatcher; +import org.apache.rat.inspector.AbstractInspector; +import org.apache.rat.inspector.Inspector; public class MyMatcher extends AbstractSimpleMatcher { public MyMatcher() { @@ -479,6 +481,11 @@ public class MyMatcher extends AbstractSimpleMatcher { public boolean matches(IHeaders headers) { return true; } + + @Override + public Inspector getInspector() { + return AbstractInspector.matcher("MyCustomMatcher", getId(), null); + } } ]]> From 80f83021990a6f2b38f74a40ac5b946f524f49bb Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 21 Jan 2024 15:00:03 +0100 Subject: [PATCH 18/77] fixed javadoc error --- .../org/apache/rat/report/AbstractReport.java | 15 ++++++++++----- 1 file changed, 10 insertions(+), 5 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java index 3e5258375..1f5291658 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java @@ -15,38 +15,43 @@ * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * - */ + */ package org.apache.rat.report; -import java.io.IOException; - import org.apache.rat.api.Document; import org.apache.rat.api.RatException; - /** * Abstract base class for deriving implementations of {@link RatReport}. */ public abstract class AbstractReport implements RatReport { /** * Empty default implementation. - * @throws IOException + * + * @throws RatException on error */ + @Override public void startReport() throws RatException { // Does nothing } /** * Empty default implementation. + * * @param document the actual document + * @Throws RatException on error. */ + @Override public void report(Document document) throws RatException { // Does nothing } /** * Empty default implementation. + * + * @Throws RatException on error. */ + @Override public void endReport() throws RatException { // Does nothing } From 58dd6b0f6db831569a69fb46cc7e2d34c386f021 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 21 Jan 2024 23:15:03 +0100 Subject: [PATCH 19/77] fixedup javadoc --- .../src/main/java/org/apache/rat/ReportConfiguration.java | 1 + .../java/org/apache/rat/analysis/DefaultAnalyserFactory.java | 2 ++ .../org/apache/rat/annotation/ApacheV2LicenseAppender.java | 4 +++- .../org/apache/rat/configuration/builders/SpdxBuilder.java | 4 ++-- .../src/main/java/org/apache/rat/inspector/Inspector.java | 2 +- .../src/main/java/org/apache/rat/report/AbstractReport.java | 4 ++-- 6 files changed, 11 insertions(+), 6 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 fd5e3d7b3..c842d37a9 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 @@ -373,6 +373,7 @@ public void addLicense(ILicense license) { * of approved 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(ILicense.Builder builder) { if (builder != null) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java index e149b78e5..3178cd051 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/DefaultAnalyserFactory.java @@ -37,6 +37,7 @@ public class DefaultAnalyserFactory { /** * Creates a DocumentAnalyser from a collection of ILicenses. + * @param log The Log to use for logging. * @param licenses The licenses to use in the Analyser. * @return A document analyser that uses the provides licenses. */ @@ -61,6 +62,7 @@ private final static class DefaultAnalyser implements IDocumentAnalyser { /** * Constructs a DocumentAnalyser for the specified license. + * * @param license The license to analyse */ public DefaultAnalyser(final Log log, final Collection licenses) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java b/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java index 8c4ccf7d0..34c6dec84 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java +++ b/apache-rat-core/src/main/java/org/apache/rat/annotation/ApacheV2LicenseAppender.java @@ -36,6 +36,7 @@ public class ApacheV2LicenseAppender extends AbstractLicenseAppender { /** * Create a license appender with the standard ASF license header. + * @param log The log to use during processing. */ public ApacheV2LicenseAppender(final Log log) { super(log); @@ -45,7 +46,8 @@ public ApacheV2LicenseAppender(final Log log) { * Create a license appender with the given copyright line. This should be of * the form "Copyright 2008 Foo" * - * @param copyright copyright line. + * @param log The log to use during processing. + * @param copyright copyright line to add to the headers. */ public ApacheV2LicenseAppender(final Log log, String copyright) { super(log); diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java index 42530147d..a65f08259 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java @@ -32,8 +32,8 @@ public class SpdxBuilder extends AbstractBuilder { /** * sets the name for the SPDX matcher - * @param name - * @return + * @param name The text that follows the colon ':' in the SPDX tag. + * @return this builder for chaining. */ public SpdxBuilder setName(String name) { Objects.requireNonNull(name, "name must not be null"); diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java index 346513f0b..49d3552ed 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java +++ b/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java @@ -34,7 +34,7 @@ public enum Type { License, Matcher, Parameter, Text }; /** * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) - * @return + * @return The common name for the item being inspected. */ String getCommonName(); diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java index 1f5291658..89c6c9b75 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/AbstractReport.java @@ -39,7 +39,7 @@ public void startReport() throws RatException { * Empty default implementation. * * @param document the actual document - * @Throws RatException on error. + * @throws RatException on error. */ @Override public void report(Document document) throws RatException { @@ -49,7 +49,7 @@ public void report(Document document) throws RatException { /** * Empty default implementation. * - * @Throws RatException on error. + * @throws RatException on error. */ @Override public void endReport() throws RatException { From 09cad95e2b7ac6a059c686656936e7b8b11b8274 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 21 Jan 2024 23:24:06 +0100 Subject: [PATCH 20/77] updated javadoc --- .../configuration/MatcherBuilderTracker.java | 3 +++ .../main/java/org/apache/rat/utils/Log.java | 21 +++++++++++++++++++ 2 files changed, 24 insertions(+) diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java index 71d435431..82fc8af44 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java @@ -36,6 +36,9 @@ */ public class MatcherBuilderTracker { + /** + * The instance of the BuildTracker. + */ public static MatcherBuilderTracker INSTANCE; private final Map> matcherBuilders; diff --git a/apache-rat-core/src/main/java/org/apache/rat/utils/Log.java b/apache-rat-core/src/main/java/org/apache/rat/utils/Log.java index 5201bdcbe..0a74c6527 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/utils/Log.java +++ b/apache-rat-core/src/main/java/org/apache/rat/utils/Log.java @@ -59,22 +59,43 @@ public enum Level { */ void log(Level level, String message); + /** + * Write a log message at the specified level. + * @param level the level to write the message at. + * @param message the mesage to write. + */ default void log(Level level, Object message) { log(level, message == null ? "NULL" : message.toString()); } + /** + * Write a message at DEBUG level. + * @param message the message to write. + */ default void debug(Object message) { log(Level.DEBUG, message); } + /** + * Write a message at INFO level. + * @param message the message to write. + */ default void info(Object message) { log(Level.INFO, message); } + /** + * Write a message at WARN level. + * @param message the message to write. + */ default void warn(Object message) { log(Level.WARN, message); } + /** + * Write a message at ERROR level. + * @param message the message to write. + */ default void error(Object message) { log(Level.ERROR, message); } From 1ef03a1cca32675b880ae81b38ee2fb01e76724a Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Fri, 15 Mar 2024 13:42:16 +0100 Subject: [PATCH 21/77] change to parameter descriptions --- .../apache/rat/analysis/IHeaderMatcher.java | 55 +++++++- .../rat/analysis/LicenseCollection.java | 35 +++-- .../apache/rat/analysis/UnknownLicense.java | 19 +-- .../rat/analysis/matchers/AndMatcher.java | 6 + .../analysis/matchers/CopyrightMatcher.java | 26 ++++ .../analysis/matchers/FullTextMatcher.java | 15 +++ .../rat/analysis/matchers/NotMatcher.java | 8 ++ .../rat/analysis/matchers/OrMatcher.java | 9 +- .../analysis/matchers/SPDXMatcherFactory.java | 12 +- .../analysis/matchers/SimpleRegexMatcher.java | 21 ++- .../analysis/matchers/SimpleTextMatcher.java | 15 +++ .../rat/config/parameters/Component.java | 56 ++++++++ .../config/parameters/DescriptionImpl.java | 39 ++++++ .../builders/MatcherRefBuilder.java | 18 +++ .../rat/inspector/AbstractInspector.java | 120 ------------------ .../org/apache/rat/inspector/Inspector.java | 63 --------- .../java/org/apache/rat/license/ILicense.java | 81 ++++++++---- .../apache/rat/license/LicenseSetFactory.java | 67 +++++----- .../org/apache/rat/license/SimpleLicense.java | 14 +- .../rat/report/ConfigurationReport.java | 38 +++--- 20 files changed, 421 insertions(+), 296 deletions(-) create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java index 3724951d7..38cd38065 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java @@ -18,6 +18,12 @@ */ package org.apache.rat.analysis; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; + +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.DescriptionImpl; import org.apache.rat.configuration.builders.AllBuilder; import org.apache.rat.configuration.builders.AnyBuilder; import org.apache.rat.configuration.builders.CopyrightBuilder; @@ -28,10 +34,11 @@ import org.apache.rat.configuration.builders.TextBuilder; /** - * Performs explicit checks against a line from the header of a file. - * For implementations that need to check multiple lines the implementation must cache the earlier lines. + * Performs explicit checks against a line from the header of a file. For + * implementations that need to check multiple lines the implementation must + * cache the earlier lines. */ -public interface IHeaderMatcher { +public interface IHeaderMatcher extends Component { /** * Get the identifier for this matcher. *

All matchers must have unique identifiers

@@ -41,8 +48,8 @@ public interface IHeaderMatcher { String getId(); /** - * Resets this state {@code State.i}. - * If text is being cached this method should clear that cache. + * Resets this state {@code State.i}. If text is being cached this method should + * clear that cache. */ void reset(); @@ -55,6 +62,44 @@ public interface IHeaderMatcher { */ boolean matches(IHeaders headers); + public class MatcherDescription extends DescriptionImpl { + private IHeaderMatcher self; + private String name; + protected Collection children; + + private Description[] baseChildren = { + new DescriptionImpl(Type.Parameter, "id", "The id of this matcher instance", self::getId), + new DescriptionImpl(Type.Parameter, "name", "The name of this matcher instance", () -> name), + new DescriptionImpl(Type.Parameter, "refId", + "This matcher is a reference to another matcher defined elsewhere", this::getRefId) }; + + public MatcherDescription(IHeaderMatcher matcher, String name, String description) { + super(Type.Matcher, name, description, null); + self = matcher; + children = new ArrayList<>(); + children.addAll(Arrays.asList(baseChildren)); + } + + public MatcherDescription addChildMatchers(Collection matchers) { + matchers.forEach(m -> children.add(m.getDescription())); + return this; + } + + public MatcherDescription addChildren(Description[] newChildren) { + children.addAll(Arrays.asList(newChildren)); + return this; + } + + protected String getRefId() { + return null; + } + + @Override + public Collection getChildren() { + return children; + } + } + /** * An IHeaderMatcher builder. */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java index 3226b576e..743f34898 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java @@ -20,19 +20,20 @@ import java.util.Collection; import java.util.Collections; +import java.util.stream.Collectors; import org.apache.rat.analysis.matchers.AbstractMatcherContainer; -import org.apache.rat.inspector.AbstractInspector; -import org.apache.rat.inspector.Inspector; +import org.apache.rat.config.parameters.DescriptionImpl; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; /** - * A collection of ILicenses that acts as a single License for purposes of Analysis. - *

- * This class process each license in turn on each {@code matches(String)} call. When a match is found the - * ILicenseFamily for the matching license is captured and used as the family for this license. If no matching - * license has been found the default {@code dummy} license category is used. + * A collection of ILicenses that acts as a single License for purposes of + * Analysis.

This class process each license in turn on each + * {@code matches(String)} call. When a match is found the ILicenseFamily for + * the matching license is captured and used as the family for this license. If + * no matching license has been found the default {@code dummy} license category + * is used. */ class LicenseCollection extends AbstractMatcherContainer implements ILicense { @@ -43,7 +44,8 @@ class LicenseCollection extends AbstractMatcherContainer implements ILicense { /** * Constructs the LicenseCollection from the provided ILicense collection. - * @param enclosed The collection of ILicenses to compose this License implementation from. May not be null. + * @param enclosed The collection of ILicenses to compose this License + * implementation from. May not be null. */ public LicenseCollection(Collection enclosed) { super(enclosed); @@ -92,16 +94,23 @@ public String getNotes() { public String derivedFrom() { return matchingLicense == null ? null : matchingLicense.derivedFrom(); } - + @Override public String getName() { return getLicenseFamily().getFamilyName(); } @Override - public Inspector getInspector() { - return AbstractInspector.license(this, matchingLicense == null ? null : matchingLicense.getInspector()); + public Description getDescription() { + if (matchingLicense != null) { + return matchingLicense.getDescription(); + } + return new DescriptionImpl(Type.License, "licenseCollection", + "A collection of ILicenses that acts as a single License for purposes of Analysis.", null) { + @Override + public Collection getChildren() { + return enclosed.stream().map(ILicense::getDescription).collect(Collectors.toList()); + } + }; } - - } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java index f947af81b..8bd054eea 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java @@ -18,20 +18,17 @@ */ package org.apache.rat.analysis; -import org.apache.rat.inspector.AbstractInspector; -import org.apache.rat.inspector.Inspector; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.ILicenseFamilyBuilder; /** - * An ILicense implementation that represents an unknown license. - *

- * The UnknownLicense is used during processing to report that a document license can not be determined. - *

+ * An ILicense implementation that represents an unknown license.

The + * UnknownLicense is used during processing to report that a document license + * can not be determined.

*/ public class UnknownLicense implements ILicense { - + /** * The single instance of this class. */ @@ -46,7 +43,7 @@ private UnknownLicense() { family = new ILicenseFamilyBuilder().setLicenseFamilyCategory(ILicenseFamily.UNKNOWN_CATEGORY) .setLicenseFamilyName("Unknown license").build(); } - + @Override public String getId() { return ILicenseFamily.UNKNOWN_CATEGORY; @@ -86,4 +83,10 @@ public String getName() { public String derivedFrom() { return null; } + + @Override + public Description getDescription() { + return new ILicense.ILicenseDescription(this, null); + } + } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java index 91b9fab29..6d19b50c1 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java @@ -55,4 +55,10 @@ public boolean matches(IHeaders headers) { } return true; } + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "all", "Returns true if all enclosed matchers return true.") + .addChildMatchers(enclosed); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java index 9dc1d019b..5dbeaea86 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java @@ -23,6 +23,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.DescriptionImpl; /** * Matches a typical Copyright header line only based on a regex pattern which @@ -59,6 +61,11 @@ public class CopyrightMatcher extends AbstractSimpleMatcher { private final Pattern dateOwnerPattern; private final Pattern ownerDatePattern; + private final Description[] children = { + new DescriptionImpl(Type.Parameter, "start", "The initial date of the copyright", this::getStart), + new DescriptionImpl(Type.Parameter, "stop", "The last date the copyright we modifed", this::getStop), + new DescriptionImpl(Type.Parameter, "owner", "The owner of the copyright", this::getOwner), }; + /** * Constructs the CopyrightMatcher with the specified start, stop and owner strings and a unique random id.. * @param start the start date for the copyright may be null. @@ -105,6 +112,18 @@ public CopyrightMatcher(String id, String start, String stop, String owner) { } } + private String getStart() { + return start; + } + + private String getStop() { + return stop; + } + + private String getOwner() { + return owner; + } + @Override public boolean matches(IHeaders headers) { String lowerLine = headers.raw().toLowerCase(); @@ -124,4 +143,11 @@ public boolean matches(IHeaders headers) { } return false; } + + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "copyright", "Matches copyright statements") + .addChildren(children); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java index 6b121af7e..2736606f4 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java @@ -21,6 +21,8 @@ import java.util.Locale; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.DescriptionImpl; /** * Accumulates all letters and numbers contained inside the header and compares @@ -34,9 +36,12 @@ public class FullTextMatcher extends AbstractSimpleMatcher { private final String fullText; + private Description[] children = { new DescriptionImpl(Type.Text, "", "The text to match", this::getFullText) }; + /** * Constructs the full text matcher with a unique random id and the specified * text to match. + * * @param fullText the text to match */ public FullTextMatcher(String fullText) { @@ -45,6 +50,7 @@ public FullTextMatcher(String fullText) { /** * Constructs the full text matcher for the specified text. + * * @param id the id for the matcher * @param fullText the text to match */ @@ -53,6 +59,10 @@ public FullTextMatcher(String id, String fullText) { this.fullText = prune(fullText).toLowerCase(Locale.ENGLISH); } + private String getFullText() { + return fullText; + } + /** * Removes everything except letter or digit from text. * @@ -78,4 +88,9 @@ public boolean matches(IHeaders headers) { } return false; } + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "text", "Matches text statement").addChildren(children); + } } \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java index ca5173e67..14ca6ebff 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java @@ -31,6 +31,7 @@ public class NotMatcher extends AbstractHeaderMatcher { /** * Create the matcher with the enclosed matcher. + * * @param enclosed the enclosed matcher */ public NotMatcher(IHeaderMatcher enclosed) { @@ -39,6 +40,7 @@ public NotMatcher(IHeaderMatcher enclosed) { /** * Create the matcher with the enclosed matcher and id. + * * @param id the id for this matcher. * @param enclosed the enclosed matcher */ @@ -57,4 +59,10 @@ public boolean matches(IHeaders headers) { public void reset() { enclosed.reset(); } + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "not", "negates the enclosed matcher.") + .addChildMatchers(Arrays.asList(enclosed)); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java index c9117ff1a..a7671eee3 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java @@ -30,6 +30,7 @@ public class OrMatcher extends AbstractMatcherContainer { /** * Constructs the matcher from the enclosed matchers. + * * @param enclosed the enclosed matchers. */ public OrMatcher(Collection enclosed) { @@ -38,6 +39,7 @@ public OrMatcher(Collection enclosed) { /** * Constructs the matcher with the specified id from the enclosed matchers. + * * @param id the id to use. * @param enclosed the enclosed matchers. */ @@ -55,4 +57,9 @@ public boolean matches(IHeaders headers) { } return false; } -} + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "or", + "Returns true if one of the enclosed matchers return true.").addChildMatchers(enclosed); + }} diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java index a0311c433..e13ca58f6 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java @@ -68,10 +68,11 @@ public class SPDXMatcherFactory { private SPDXMatcherFactory() { lastLine = null; - }; + } /** * Creates the spdx matcher. + * * @param spdxId the spdx name to match. * @return a spdx matcher. */ @@ -89,6 +90,7 @@ public IHeaderMatcher create(String spdxId) { /** * Each matcher calls this method to present the line it is working on. + * * @param line The line the caller is looking at. * @param caller the Match that is calling this method. * @return true if the caller matches the text. @@ -114,7 +116,7 @@ public class Match extends AbstractSimpleMatcher { String spdxId; /** * Constructor. - * + * * @param spdxId A regular expression that matches the @{short-name} of the SPDX * Identifier. */ @@ -135,5 +137,11 @@ public void reset() { SPDXMatcherFactory.this.lastMatch = null; } + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "spdx", "Matches SPDX license identifier in the text") + .addChildren(children); + } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index 83b75a7fb..b9b393d2b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -18,11 +18,10 @@ */ package org.apache.rat.analysis.matchers; -import java.util.Arrays; import java.util.regex.Pattern; -import org.apache.rat.inspector.AbstractInspector; -import org.apache.rat.inspector.Inspector; +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.DescriptionImpl; import org.apache.rat.analysis.IHeaders; @@ -32,10 +31,13 @@ public class SimpleRegexMatcher extends AbstractSimpleMatcher { private final Pattern pattern; + private Description[] children = { + new DescriptionImpl(Type.Text, "", "The regex pattern to match", this::getPattern) }; + /** * Constructs a regex pattern matcher with a unique random id and the specified * Regex pattern. - * + * * @param pattern the pattern to match. Pattern will only match a single line * from the input stream. */ @@ -46,7 +48,7 @@ public SimpleRegexMatcher(Pattern pattern) { /** * Constructs a regex pattern matcher with a unique random id and the specified * Regex pattern. - * + * * @param id the id for this matcher * @param pattern the pattern to match. Pattern will only match a single line * from the input stream. @@ -56,13 +58,18 @@ public SimpleRegexMatcher(String id, Pattern pattern) { this.pattern = pattern; } + private String getPattern() { + return pattern.pattern(); + } + @Override public boolean matches(IHeaders headers) { return pattern.matcher(headers.raw()).find(); } @Override - public Inspector getInspector() { - return AbstractInspector.matcher("regex", getId(), Arrays.asList(AbstractInspector.text(pattern.toString()))); + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "regex", "Performs a regex match on the text") + .addChildren(children); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java index 61085ad51..4e29b3306 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java @@ -20,6 +20,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.DescriptionImpl; /** * A simple text matching IHeaderMatcher implementation. @@ -27,8 +29,11 @@ public class SimpleTextMatcher extends AbstractSimpleMatcher { private final String pattern; + private Description[] children = { new DescriptionImpl(Type.Text, "", "The text to match", this::getSimpleText) }; + /** * Constructs the simple text matcher for the simple string. + * * @param pattern The pattern to match. Will only match a single line from the input stream. */ public SimpleTextMatcher(String pattern) { @@ -37,6 +42,7 @@ public SimpleTextMatcher(String pattern) { /** * Constructs the simple text matcher for the simple string. + * * @param id The id for this matcher. * @param pattern The pattern to match. Will only match a single line from the input stream. */ @@ -48,8 +54,17 @@ public SimpleTextMatcher(String id, String pattern) { this.pattern = pattern; } + private String getSimpleText() { + return this.pattern; + } + @Override public boolean matches(IHeaders headers) { return headers.raw().contains(pattern); } + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "text", "Matches text statement").addChildren(children); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java new file mode 100644 index 000000000..9ada3733d --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java @@ -0,0 +1,56 @@ +package org.apache.rat.config.parameters; + +import java.util.Collection; +import java.util.Collections; +import java.util.stream.Collectors; + + +public interface Component { + public enum Type { License, Matcher, Parameter, Text }; + + /** + * Returns the component Description. + * @return the component description. + */ + Description getDescription(); + + interface Description { + public Type getType(); + + /** + * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) + * @return The common name for the item being inspected. + */ + String getCommonName(); + + /** + * Gets the description of descriptive text for the component. + * @return the descriptive text; + */ + String getDescription(); + + /** + * Gets the string parameter value if this inspector has no + * @return the string value (default returns an empty string. + */ + String getParamValue(); + + /** + * Gets a map of the parameters that the object contains. For example Copyright has 'start', 'stop', and 'owner' + * parameters. Some IHeaderMatchers have simple text values (e.g. 'regex' or 'text' types) these should list + * an unnamed parameter (empty string) with the text value. + * @return the map of parameters to the objects that represent them. + */ + default Collection getChildren() { return Collections.emptyList(); } + + /** + * Get all the children of a specific type + * @param type the type to return + * @return the collection of children of the specified type. + */ + default Collection childrenOfType(Type type) { + return getChildren().stream().filter(i -> i.getType() == type).collect(Collectors.toList()); + } + } + +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java new file mode 100644 index 000000000..6e9c42af2 --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java @@ -0,0 +1,39 @@ +package org.apache.rat.config.parameters; + +import java.util.function.Supplier; + +import org.apache.rat.config.parameters.Component.Type; + +public class DescriptionImpl implements Component.Description { + private final Type type; + private final String name; + private final String desc; + private final Supplier getter; + + public DescriptionImpl(Type type, String name, String desc, Supplier getter) { + this.type = type; + this.name = name; + this.desc = desc; + this.getter = getter == null ? () -> "" : getter;; + } + + @Override + public Type getType() { + return type; + } + + @Override + public String getCommonName() { + return name; + } + + @Override + public String getDescription() { + return desc; + } + + @Override + public String getParamValue() { + return getter.get(); + } +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java index 5e46d67a8..a5268cb4f 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java @@ -18,12 +18,18 @@ */ package org.apache.rat.configuration.builders; +import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; import java.util.Map; +import java.util.stream.Collectors; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.analysis.IHeaderMatcher.MatcherDescription; +import org.apache.rat.config.parameters.DescriptionImpl; +import org.apache.rat.config.parameters.Component.Description; +import org.apache.rat.license.ILicense; /** * A reference matching Matcher builder. @@ -112,5 +118,17 @@ public boolean matches(IHeaders headers) { checkProxy(); return wrapped.matches(headers); } + + @Override + public Description getDescription() { + + return new MatcherDescription(this, "MatcherProxy", "A proxy to another Matcher") { + + @Override + public String getRefId() { + return proxyId; + } + }; + } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java deleted file mode 100644 index 8b1525575..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/inspector/AbstractInspector.java +++ /dev/null @@ -1,120 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - */ -package org.apache.rat.inspector; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.List; - -import org.apache.rat.license.ILicense; - -public abstract class AbstractInspector implements Inspector { - private final Type type; - private final String name; - - public AbstractInspector(Type type, String name) { - this.type = type; - this.name = name; - } - - @Override - public Type getType() { - return type; - } - - @Override - public String getCommonName() { - return name; - } - - public static Inspector license(ILicense license, Inspector matcher) { - return new AbstractInspector(Inspector.Type.License, "license") { - - @Override - public Collection getChildren() { - List result = new ArrayList<>(); - if (!license.getName().equals(license.getLicenseFamily().getFamilyName())) { - result.add(parameter("name", license.getName())); - } - if (!license.getId().equals(license.getLicenseFamily().getFamilyCategory().trim())) { - result.add(parameter("id", license.getId())); - } - result.add(parameter("family", license.getLicenseFamily().getFamilyCategory().trim())); - result.add(parameter("notes", license.getNotes())); - if (matcher != null) { - result.add(matcher); - } - return result; - } - }; - } - - public static Inspector parameter(String name, String value) { - return new Inspector() { - @Override - public Inspector.Type getType() { - return Inspector.Type.Parameter; - } - - @Override - public String getCommonName() { - return name; - } - - @Override - public String getParamValue() { - return value == null ? "" : value; - } - }; - } - - public static Inspector text(String value) { - return new Inspector() { - @Override - public Inspector.Type getType() { - return Inspector.Type.Text; - } - - @Override - public String getCommonName() { - return ""; - } - - @Override - public String getParamValue() { - return value == null ? "" : value; - } - }; - } - - public static Inspector matcher(String name, String id, Collection children) { - return new AbstractInspector(Type.Matcher, name) { - @Override - public Collection getChildren() { - List result = new ArrayList<>(); - result.add(parameter("id", id)); - if (children != null) { - result.addAll(children); - } - return result; - } - }; - } - -} diff --git a/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java b/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java deleted file mode 100644 index 49d3552ed..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/inspector/Inspector.java +++ /dev/null @@ -1,63 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one * - * or more contributor license agreements. See the NOTICE file * - * distributed with this work for additional information * - * regarding copyright ownership. The ASF licenses this file * - * to you under the Apache License, Version 2.0 (the * - * "License"); you may not use this file except in compliance * - * with the License. You may obtain a copy of the License at * - * * - * http://www.apache.org/licenses/LICENSE-2.0 * - * * - * Unless required by applicable law or agreed to in writing, * - * software distributed under the License is distributed on an * - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY * - * KIND, either express or implied. See the License for the * - * specific language governing permissions and limitations * - * under the License. * - */ -package org.apache.rat.inspector; - -import java.util.Collection; -import java.util.Collections; -import java.util.stream.Collectors; - - -/** - * An interface that explains what the matcher operates on. - */ -public interface Inspector { - - public enum Type { License, Matcher, Parameter, Text }; - - public Type getType(); - - /** - * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) - * @return The common name for the item being inspected. - */ - String getCommonName(); - - /** - * Gets the string parameter value if this inspector has no - * @return the string value (default returns an empty string. - */ - default String getParamValue() { return ""; } - - /** - * Gets a map of the parameters that the object contains. For example Copyright has 'start', 'stop', and 'owner' - * parameters. Some IHeaderMatchers have simple text values (e.g. 'regex' or 'text' types) these should list - * an unnamed parameter (empty string) with the text value. - * @return the map of parameters to the objects that represent them. - */ - default Collection getChildren() { return Collections.emptyList(); } - - /** - * Get all the children of a specific type - * @param type the type to return - * @return the colleciton of children of the specified type. - */ - default Collection childrenOfType(Type type) { - return getChildren().stream().filter(i -> i.getType() == type).collect(Collectors.toList()); - } -} \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java index 4d30ff2d7..37619c1c0 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java @@ -18,23 +18,29 @@ */ package org.apache.rat.license; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collection; import java.util.Comparator; +import java.util.List; import java.util.Objects; import java.util.SortedSet; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.DescriptionImpl; /** * The definition of a License. */ -public interface ILicense extends IHeaderMatcher, Comparable { +public interface ILicense extends IHeaderMatcher, Comparable, Component { /** * @return the ILicenseFamily implementation for this license. */ ILicenseFamily getLicenseFamily(); /** - * @return the notes associated with this license. May be null or empty. + * @return the notes associated with this license. May be null or empty. */ String getNotes(); @@ -42,9 +48,10 @@ public interface ILicense extends IHeaderMatcher, Comparable { * @return the id of a license that this license is derived from. May be null. */ String derivedFrom(); - + /** - * Returns the name of this license. If no name was specified then the name of the family is returned. + * Returns the name of this license. If no name was specified then the name of + * the family is returned. * @return the name of this license. */ String getName(); @@ -57,25 +64,52 @@ static ILicense.Builder builder() { } /** - * @return The comparator for used to sort Licenses. + * @return The comparator for used to sort Licenses. */ static Comparator getComparator() { return Comparator.comparing(IHeaderMatcher::getId); } + class ILicenseDescription extends DescriptionImpl { + private ILicense self; + private IHeaderMatcher matcher; + + Description[] children = { + new DescriptionImpl(Type.Parameter, "name", "The name of this license", self::getName), + new DescriptionImpl(Type.Parameter, "id", "The id of this license", self::getId), + new DescriptionImpl(Type.Parameter, "family", "The family this license belongs to", + self.getLicenseFamily()::getFamilyCategory), + new DescriptionImpl(Type.Parameter, "notes", "Any notes related to this family", self::getNotes), }; + + public ILicenseDescription(ILicense license, IHeaderMatcher matcher) { + super(Type.License, "license", "A license definition", null); + self = license; + this.matcher = matcher; + } + + @Override + public Collection getChildren() { + List result = new ArrayList<>(); + result.addAll(Arrays.asList(children)); + result.add(matcher.getDescription()); + return result; + } + + } + /** * A builder for ILicense instances. */ - class Builder { + class Builder { private IHeaderMatcher.Builder matcher; private String notes; private String derivedFrom; - + private String name; - + private String id; private final ILicenseFamily.Builder licenseFamily = ILicenseFamily.builder(); @@ -96,13 +130,13 @@ public Builder setMatcher(IHeaderMatcher.Builder matcher) { * @return this builder for chaining. */ public Builder setMatcher(IHeaderMatcher matcher) { - this.matcher = ()->matcher; + this.matcher = () -> matcher; return this; } /** - * Sets the notes for the license. - * If called multiple times the notes are concatenated to create a single note. + * Sets the notes for the license. If called multiple times the notes are + * concatenated to create a single note. * @param notes the notes for the license. * @return this builder for chaining. */ @@ -112,8 +146,8 @@ public Builder setNotes(String notes) { } /** - * Sets the ID of the license. - * If the ID is not set then the ID of the license family is used. + * 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 * @return this builder for chaining. */ @@ -124,7 +158,8 @@ public Builder setId(String id) { /** * Sets the derived from fields in the license. - * @param derivedFrom the family category of the license this license was derived from. + * @param derivedFrom the family category of the license this license was + * derived from. * @return this builder for chaining. */ public Builder setDerivedFrom(String derivedFrom) { @@ -133,10 +168,10 @@ public Builder setDerivedFrom(String derivedFrom) { } /** - * Set the family category for this license. - * The category must be unique across all licenses and must be 5 characters. If more than - * 5 characters are provided then only the first 5 are taken. If fewer than 5 characters are provided - * the category is padded with spaces. + * Set the family category for this license. The category must be unique across + * all licenses and must be 5 characters. If more than 5 characters are provided + * then only the first 5 are taken. If fewer than 5 characters are provided the + * category is padded with spaces. * @param licenseFamilyCategory the family category for the license. * @return this builder for chaining. */ @@ -147,8 +182,8 @@ public Builder setLicenseFamilyCategory(String licenseFamilyCategory) { } /** - * Sets the name of the license. - * If the name is not set then the name of the license family is used. + * 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 * @return this builder for chaining. */ @@ -162,10 +197,10 @@ public Builder setName(String name) { * @return A new License implementation. */ public ILicense build(SortedSet licenseFamilies) { - Objects.requireNonNull(matcher, "Matcher must not be null"); + Objects.requireNonNull(matcher, "Matcher must not be null"); ILicenseFamily family = LicenseFamilySetFactory.search(licenseFamily.build(), licenseFamilies); - Objects.requireNonNull(family, "License family "+licenseFamily.getCategory()+" not found."); - return new SimpleLicense(family, matcher.build(), derivedFrom, notes, name, id); + Objects.requireNonNull(family, "License family " + licenseFamily.getCategory() + " not found."); + return new SimpleLicense(family, matcher.build(), derivedFrom, notes, name, id); } } } 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 750c8d179..d32a99b11 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 @@ -15,7 +15,8 @@ * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * - */package org.apache.rat.license; + */ +package org.apache.rat.license; import java.util.Collection; import java.util.Collections; @@ -25,10 +26,11 @@ import org.apache.rat.analysis.IHeaders; /** - * Class to take a set of ILicenses and collection of approved license categories and extract Subsets. + * Class to take a set of ILicenses and collection of approved license + * categories and extract Subsets. */ public class LicenseSetFactory { - + /** * An enum that defines the types of Licenses to extract. */ @@ -39,12 +41,12 @@ public enum LicenseFilter { approved, /** No licenses are returned */ none; - - /** - * Converts from a String to an enum value. - * @param s String representation. - * @return given licenseFilter for the given String representation. - */ + + /** + * Converts from a String to an enum value. + * @param s String representation. + * @return given licenseFilter for the given String representation. + */ static public LicenseFilter fromText(String s) { return LicenseFilter.valueOf(s.toLowerCase()); } @@ -52,9 +54,10 @@ static public LicenseFilter fromText(String s) { private final SortedSet licenses; private final Collection approvedLicenses; - + /** - * Constructs a factory with the specified set of Licenses and the approved license collection. + * Constructs a factory with the specified set of Licenses and the approved + * license collection. * @param licenses the set of defined licenses. * @param approvedLicenses the list of approved licenses. */ @@ -62,7 +65,7 @@ public LicenseSetFactory(SortedSet licenses, Collection approv this.licenses = licenses; this.approvedLicenses = approvedLicenses; } - + /** * Create an empty sorted Set with proper comparator. * @return An empty sorted set of ILicense objects. @@ -78,7 +81,7 @@ public static SortedSet emptyLicenseSet() { */ private static SortedSet extractFamily(Collection licenses) { SortedSet result = new TreeSet<>(); - licenses.stream().map( ILicense::getLicenseFamily ).forEach(result::add); + licenses.stream().map(ILicense::getLicenseFamily).forEach(result::add); return result; } @@ -101,7 +104,7 @@ public SortedSet getLicenses(LicenseFilter filter) { return Collections.emptySortedSet(); } } - + /** * Gets the LicenseFamily objects based on the filter. * @param filter the types of LicenseFamily objects to return. @@ -114,15 +117,14 @@ public SortedSet getLicenseFamilies(LicenseFilter filter) { case approved: SortedSet result = LicenseFamilySetFactory.emptyLicenseFamilySet(); licenses.stream().map(ILicense::getLicenseFamily) - .filter(x -> approvedLicenses.contains(x.getFamilyCategory())) - .forEach(result::add); + .filter(x -> approvedLicenses.contains(x.getFamilyCategory())).forEach(result::add); return result; case none: default: return Collections.emptySortedSet(); } } - + /** * Gets the categories of LicenseFamily objects based on the filter. * @param filter the types of LicenseFamily objects to return. @@ -132,8 +134,7 @@ public SortedSet getLicenseFamilyIds(LicenseFilter filter) { SortedSet result = new TreeSet<>(); switch (filter) { case all: - licenses.stream().map(x -> x.getLicenseFamily().getFamilyCategory()) - .forEach(result::add); + licenses.stream().map(x -> x.getLicenseFamily().getFamilyCategory()).forEach(result::add); break; case approved: result.addAll(approvedLicenses); @@ -147,7 +148,7 @@ public SortedSet getLicenseFamilyIds(LicenseFilter filter) { /** * Search a SortedSet of licenses for the matching license id. - * + * * @param licenseId the id to search for. * @param licenses the SortedSet of licenses to search. * @return the matching license or {@code null} if not found. @@ -156,54 +157,58 @@ public static ILicense search(String licenseId, SortedSet licenses) { ILicenseFamily searchFamily = ILicenseFamily.builder().setLicenseFamilyCategory(licenseId) .setLicenseFamilyName("searching proxy").build(); ILicense target = new ILicense() { - + @Override public String getId() { return licenseId; } - + @Override public void reset() { // do nothing } - + @Override public boolean matches(IHeaders headers) { return false; } - + @Override public int compareTo(ILicense arg0) { return searchFamily.compareTo(arg0.getLicenseFamily()); } - + @Override public ILicenseFamily getLicenseFamily() { return searchFamily; } - + @Override public String getNotes() { return null; } - + @Override public String derivedFrom() { return null; } - + @Override public String getName() { return searchFamily.getFamilyName(); } - + + @Override + public Description getDescription() { + return new ILicenseDescription(this, null); + } }; return search(target, licenses); } /** * Search a SortedSet of licenses for the matching license. - * + * * @param target the license to search for. * @param licenses the SortedSet of licenses to search. * @return the matching license or {@code null} if not found. @@ -212,5 +217,5 @@ public static ILicense search(ILicense target, SortedSet licenses) { SortedSet part = licenses.tailSet(target); return (!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 86c4be012..b14aa1f1b 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 @@ -36,9 +36,10 @@ class SimpleLicense implements ILicense { private String name; private String id; - SimpleLicense(ILicenseFamily family, IHeaderMatcher matcher, String derivedFrom, String notes, String name, String id) { + SimpleLicense(ILicenseFamily family, IHeaderMatcher matcher, String derivedFrom, String notes, String name, + String id) { Objects.requireNonNull(matcher, "Matcher must not be null"); - Objects.requireNonNull(family, "Family must not be null"); + Objects.requireNonNull(family, "Family must not be null"); this.family = family; this.matcher = matcher; this.derivedFrom = derivedFrom; @@ -49,7 +50,7 @@ class SimpleLicense implements ILicense { @Override public String toString() { - return String.format( "%s:%s", getId(), getName()); + return String.format("%s:%s", getId(), getName()); } public ILicenseFamily getFamily() { @@ -106,9 +107,14 @@ public String getNotes() { public String derivedFrom() { return derivedFrom; } - + @Override public String getName() { return name; } + + @Override + public Description getDescription() { + return new ILicense.ILicenseDescription(this, matcher); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java index 799f2b307..401fdd21b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -15,7 +15,7 @@ * KIND, either express or implied. See the License for the * * specific language governing permissions and limitations * * under the License. * - */ + */ package org.apache.rat.report; import java.io.IOException; @@ -28,11 +28,11 @@ import org.apache.rat.ReportConfiguration; import org.apache.rat.api.RatException; +import org.apache.rat.config.parameters.Component.Description; +import org.apache.rat.config.parameters.Component.Type; import org.apache.rat.configuration.MatcherBuilderTracker; import org.apache.rat.configuration.XMLConfigurationReader; import org.apache.rat.configuration.builders.MatcherRefBuilder; -import org.apache.rat.inspector.Inspector; -import org.apache.rat.inspector.Inspector.Type; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; @@ -71,7 +71,7 @@ public void startReport() throws RatException { if (!licenses.isEmpty()) { writer.openElement(XMLConfigurationReader.LICENSES); for (ILicense license : licenses) { - writeInspector(license.getInspector()); + writeDescription(license.getDescription()); } writer.closeElement();// LICENSES } @@ -111,22 +111,22 @@ private void writeFamily(ILicenseFamily family) throws RatException { } } - private void writeInspectors(Collection inspectors) throws RatException { - for (Inspector inspector : inspectors) { - writeInspector(inspector); + private void writeDescriptions(Collection descriptions) throws RatException { + for (Description description : descriptions) { + writeDescription(description); } } - private void writeInspector(Inspector inspector) throws RatException { - if (inspector == null) { + private void writeDescription(Description description) throws RatException { + if (description == null) { return; } try { - switch (inspector.getType()) { + switch (description.getType()) { case Matcher: // see if id was registered - Optional id = inspector.getChildren().stream().filter( - i -> i.getType() == Type.Parameter && i.getCommonName().equals(XMLConfigurationReader.ATT_ID)) + Optional id = description.getChildren().stream().filter( + i -> i.getType() == Type.Parameter && XMLConfigurationReader.ATT_ID.equals(i.getCommonName())) .findFirst(); if (id.isPresent()) { String idStr = id.get().getParamValue(); @@ -136,29 +136,29 @@ private void writeInspector(Inspector inspector) throws RatException { } matchers.add(idStr); } - writer.openElement(inspector.getCommonName()); - writeInspectors(inspector.getChildren()); + writer.openElement(description.getCommonName()); + writeDescriptions(description.getChildren()); writer.closeElement(); break; case License: writer.openElement(XMLConfigurationReader.LICENSE); - writeInspectors(inspector.getChildren()); + writeDescriptions(description.getChildren()); writer.closeElement(); break; case Parameter: - if (inspector.getCommonName().equals("id")) { + if ("id".equals(description.getCommonName())) { try { // if a UUID skip it. - UUID.fromString(inspector.getParamValue()); + UUID.fromString(description.getParamValue()); return; } catch (IllegalArgumentException expected) { // do nothing. } } - writer.attribute(inspector.getCommonName(), inspector.getParamValue()); + writer.attribute(description.getCommonName(), description.getParamValue()); break; case Text: - writer.content(inspector.getParamValue()); + writer.content(description.getParamValue()); break; } } catch (IOException e) { From 8ec9eb4a0a780c8cfc465ef95b237d446977afe4 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Fri, 15 Mar 2024 15:49:17 +0100 Subject: [PATCH 22/77] fixes some issues --- .../main/java/org/apache/rat/analysis/IHeaderMatcher.java | 2 +- .../src/main/java/org/apache/rat/license/ILicense.java | 8 ++++---- .../java/org/apache/rat/report/ConfigurationReport.java | 5 ++++- .../org/apache/rat/report/ConfigurationReportTest.java | 1 + .../java/org/apache/rat/testhelpers/TestingLicense.java | 5 +++++ .../java/org/apache/rat/testhelpers/TestingMatcher.java | 7 +++++++ 6 files changed, 22 insertions(+), 6 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java index 38cd38065..353ce6643 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java @@ -68,7 +68,7 @@ public class MatcherDescription extends DescriptionImpl { protected Collection children; private Description[] baseChildren = { - new DescriptionImpl(Type.Parameter, "id", "The id of this matcher instance", self::getId), + new DescriptionImpl(Type.Parameter, "id", "The id of this matcher instance", () -> self.getId()), new DescriptionImpl(Type.Parameter, "name", "The name of this matcher instance", () -> name), new DescriptionImpl(Type.Parameter, "refId", "This matcher is a reference to another matcher defined elsewhere", this::getRefId) }; diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java index 37619c1c0..2f917bfa2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java @@ -75,11 +75,11 @@ class ILicenseDescription extends DescriptionImpl { private IHeaderMatcher matcher; Description[] children = { - new DescriptionImpl(Type.Parameter, "name", "The name of this license", self::getName), - new DescriptionImpl(Type.Parameter, "id", "The id of this license", self::getId), + new DescriptionImpl(Type.Parameter, "name", "The name of this license", () -> self.getName()), + new DescriptionImpl(Type.Parameter, "id", "The id of this license", () -> self.getId()), new DescriptionImpl(Type.Parameter, "family", "The family this license belongs to", - self.getLicenseFamily()::getFamilyCategory), - new DescriptionImpl(Type.Parameter, "notes", "Any notes related to this family", self::getNotes), }; + () -> self.getLicenseFamily().getFamilyCategory()), + new DescriptionImpl(Type.Parameter, "notes", "Any notes related to this family", () -> self.getNotes()), }; public ILicenseDescription(ILicense license, IHeaderMatcher matcher) { super(Type.License, "license", "A license definition", null); diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java index 401fdd21b..519c7b3e1 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -155,7 +155,10 @@ private void writeDescription(Description description) throws RatException { // do nothing. } } - writer.attribute(description.getCommonName(), description.getParamValue()); + String paramValue = description.getParamValue(); + if (paramValue != null) { + writer.attribute(description.getCommonName(), paramValue); + } break; case Text: writer.content(description.getParamValue()); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java index b3ac3111f..76ccf2ff6 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java @@ -47,6 +47,7 @@ public void testAll() throws RatException, IOException { report.endReport(); writer.closeDocument(); String result = sw.toString(); + System.out.println( result ); // AssertTrue( result.contains( "")); } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java index ea3bd1ee9..96e39ab14 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java @@ -165,4 +165,9 @@ public String derivedFrom() { return derivedFrom; } + @Override + public Description getDescription() { + return new ILicense.ILicenseDescription(this, matcher); + } + } diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java index b50711b4d..93701693b 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingMatcher.java @@ -22,7 +22,9 @@ import java.util.Queue; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.AbstractHeaderMatcher; +import org.apache.rat.config.parameters.Component.Description; /** * An Matcher for testing. @@ -80,4 +82,9 @@ public void reset() { this.results.add(b); } } + + @Override + public Description getDescription() { + return new IHeaderMatcher.MatcherDescription(this, "TestingMatcher", "Matcher used in testing"); + } } \ No newline at end of file From 4ee76f8379b56fb7fffb7b41725c011cb7f4a245 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Fri, 22 Mar 2024 10:41:24 +0100 Subject: [PATCH 23/77] Switched to annotation based markers --- .../org/apache/rat/ReportConfiguration.java | 2 +- .../apache/rat/analysis/IHeaderMatcher.java | 42 +-------- .../rat/analysis/LicenseCollection.java | 24 +++-- .../apache/rat/analysis/UnknownLicense.java | 14 +-- .../matchers/AbstractHeaderMatcher.java | 10 +++ .../matchers/AbstractMatcherContainer.java | 8 ++ .../rat/analysis/matchers/AndMatcher.java | 5 ++ .../analysis/matchers/CopyrightMatcher.java | 29 +++--- .../rat/analysis/matchers/NotMatcher.java | 11 +++ .../rat/analysis/matchers/OrMatcher.java | 4 + .../analysis/matchers/SPDXMatcherFactory.java | 18 ++-- .../analysis/matchers/SimpleRegexMatcher.java | 15 ++-- .../analysis/matchers/SimpleTextMatcher.java | 37 ++++---- .../rat/config/parameters/Component.java | 46 +--------- .../rat/config/parameters/ConfigChildren.java | 11 +++ .../config/parameters/ConfigComponent.java | 23 +++++ .../config/parameters/ConfigParameter.java | 12 +++ .../rat/config/parameters/Description.java | 71 +++++++++++++++ .../config/parameters/DescriptionBuilder.java | 89 +++++++++++++++++++ .../config/parameters/DescriptionImpl.java | 39 -------- .../configuration/MatcherBuilderTracker.java | 1 - .../configuration/XMLConfigurationReader.java | 2 +- .../configuration/builders/AllBuilder.java | 2 +- .../configuration/builders/AnyBuilder.java | 2 +- .../configuration/builders/NotBuilder.java | 2 +- .../configuration/builders/RegexBuilder.java | 2 +- .../configuration/builders/SpdxBuilder.java | 2 +- .../configuration/builders/TextBuilder.java | 2 +- .../java/org/apache/rat/license/ILicense.java | 44 +++------ .../apache/rat/license/LicenseSetFactory.java | 14 +-- .../org/apache/rat/license/SimpleLicense.java | 13 +-- .../rat/report/ConfigurationReport.java | 32 ++++--- .../rat/report/xml/writer/IXmlWriter.java | 10 +++ .../xml/writer/impl/base/XmlWriter.java | 12 +++ .../apache/rat/license/SimpleLicenseTest.java | 33 +++++++ .../rat/testhelpers/TestingLicense.java | 47 +++++----- .../src/test/java/org/example/Matcher.java | 3 +- 37 files changed, 448 insertions(+), 285 deletions(-) create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java 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 c842d37a9..a57b82d92 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 @@ -84,7 +84,7 @@ public class ReportConfiguration { public ReportConfiguration(Log log) { this.log = log; families = new ReportingSet<>(LicenseFamilySetFactory.emptyLicenseFamilySet()).setLog(log) - .setMsgFormat( s -> String.format("Duplicate LicenseFamily category: %s", s.getFamilyCategory())); + .setMsgFormat( s -> String.format("Duplicate LicenseFamily category: %s", s.getFamilyCategory())); licenses = new ReportingSet<>(LicenseSetFactory.emptyLicenseSet()).setLog(log) .setMsgFormat( s -> String.format( "Duplicate License %s (%s) of type %s", s.getName(), s.getId(), s.getLicenseFamily().getFamilyCategory())); approvedLicenseCategories = new TreeSet<>(); diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java index 353ce6643..351338509 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java @@ -23,7 +23,8 @@ import java.util.Collection; import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.DescriptionImpl; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; import org.apache.rat.configuration.builders.AllBuilder; import org.apache.rat.configuration.builders.AnyBuilder; import org.apache.rat.configuration.builders.CopyrightBuilder; @@ -45,6 +46,7 @@ public interface IHeaderMatcher extends Component { * * @return the Identifier for this matcher. */ + @ConfigComponent(type=Component.Type.Parameter, name="id", desc="The id of this matcher.") String getId(); /** @@ -62,44 +64,6 @@ public interface IHeaderMatcher extends Component { */ boolean matches(IHeaders headers); - public class MatcherDescription extends DescriptionImpl { - private IHeaderMatcher self; - private String name; - protected Collection children; - - private Description[] baseChildren = { - new DescriptionImpl(Type.Parameter, "id", "The id of this matcher instance", () -> self.getId()), - new DescriptionImpl(Type.Parameter, "name", "The name of this matcher instance", () -> name), - new DescriptionImpl(Type.Parameter, "refId", - "This matcher is a reference to another matcher defined elsewhere", this::getRefId) }; - - public MatcherDescription(IHeaderMatcher matcher, String name, String description) { - super(Type.Matcher, name, description, null); - self = matcher; - children = new ArrayList<>(); - children.addAll(Arrays.asList(baseChildren)); - } - - public MatcherDescription addChildMatchers(Collection matchers) { - matchers.forEach(m -> children.add(m.getDescription())); - return this; - } - - public MatcherDescription addChildren(Description[] newChildren) { - children.addAll(Arrays.asList(newChildren)); - return this; - } - - protected String getRefId() { - return null; - } - - @Override - public Collection getChildren() { - return children; - } - } - /** * An IHeaderMatcher builder. */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java index 743f34898..c81088c63 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java @@ -23,7 +23,7 @@ import java.util.stream.Collectors; import org.apache.rat.analysis.matchers.AbstractMatcherContainer; -import org.apache.rat.config.parameters.DescriptionImpl; +import org.apache.rat.config.parameters.Description; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -35,6 +35,7 @@ * no matching license has been found the default {@code dummy} license category * is used. */ + class LicenseCollection extends AbstractMatcherContainer implements ILicense { private static final ILicenseFamily DEFAULT = ILicenseFamily.builder().setLicenseFamilyCategory("Dummy") @@ -89,12 +90,7 @@ public ILicenseFamily getLicenseFamily() { public String getNotes() { return matchingLicense == null ? null : matchingLicense.getNotes(); } - - @Override - public String derivedFrom() { - return matchingLicense == null ? null : matchingLicense.derivedFrom(); - } - + @Override public String getName() { return getLicenseFamily().getFamilyName(); @@ -105,12 +101,12 @@ public Description getDescription() { if (matchingLicense != null) { return matchingLicense.getDescription(); } - return new DescriptionImpl(Type.License, "licenseCollection", - "A collection of ILicenses that acts as a single License for purposes of Analysis.", null) { - @Override - public Collection getChildren() { - return enclosed.stream().map(ILicense::getDescription).collect(Collectors.toList()); - } - }; + return new Description(Type.License, "licenseCollection", + "A collection of ILicenses that acts as a single License for purposes of Analysis.", null, null); + } + + @Override + public IHeaderMatcher getMatcher() { + return matchingLicense; } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java index 8bd054eea..6e83b8dcb 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/UnknownLicense.java @@ -18,6 +18,12 @@ */ package org.apache.rat.analysis; +import java.util.Arrays; +import java.util.Collections; + +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.ILicenseFamilyBuilder; @@ -80,13 +86,7 @@ public String getName() { } @Override - public String derivedFrom() { + public IHeaderMatcher getMatcher() { return null; } - - @Override - public Description getDescription() { - return new ILicense.ILicenseDescription(this, null); - } - } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java index f3123ee32..b188cd9eb 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java @@ -22,6 +22,10 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; /** * An abstract class to simplify IHeaderMatcher creation. This class ensures @@ -41,6 +45,7 @@ protected AbstractHeaderMatcher(String id) { this.id = StringUtils.isBlank(id) ? UUID.randomUUID().toString() : id; } + @ConfigComponent(type=Component.Type.Parameter, name="id", desc="The id of the matcher.") @Override public String getId() { return id; @@ -50,4 +55,9 @@ public String getId() { public String toString() { return getId(); } + + @Override + public Description getDescription() { + return DescriptionBuilder.build(this); + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java index e03d69a84..b9515854c 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java @@ -21,8 +21,12 @@ import java.util.ArrayList; import java.util.Collection; import java.util.Objects; +import java.util.function.Consumer; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigChildren; +import org.apache.rat.config.parameters.ConfigComponent; /** * A class that implements IHeaderMatcher as a collection of other @@ -32,6 +36,10 @@ public abstract class AbstractMatcherContainer extends AbstractHeaderMatcher { protected final Collection enclosed; + @ConfigChildren(name="enclosed") + public Collection getChildren() { + return enclosed; + } /** * Constructs the abstract matcher container. If the {@code id} is not set then * a unique random identifier is created. The {@code enclosed} collection is diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java index 6d19b50c1..bdd98203b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java @@ -22,10 +22,15 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; /** * A matcher that performs a logical {@code AND} across all the contained matchers. */ +@ConfigComponent(type=Component.Type.Matcher, name="and", desc="Returns true if all enclosed matchers return true.") public class AndMatcher extends AbstractMatcherContainer { /** diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java index 5dbeaea86..0014c2850 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java @@ -24,7 +24,10 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.config.parameters.DescriptionImpl; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; /** * Matches a typical Copyright header line only based on a regex pattern which @@ -50,6 +53,7 @@ *

The matcher also accepts "(C)", "(c)", and "©" in place of (or in addition to) the "Copyright" or "copyright" * keyword

*/ +@ConfigComponent(type=Component.Type.Matcher, name="copyright", desc="Matches copyright statements.") public class CopyrightMatcher extends AbstractSimpleMatcher { private static final String COPYRIGHT_SYMBOL_DEFN = "\\([Cc]\\)|©"; @@ -61,10 +65,9 @@ public class CopyrightMatcher extends AbstractSimpleMatcher { private final Pattern dateOwnerPattern; private final Pattern ownerDatePattern; - private final Description[] children = { - new DescriptionImpl(Type.Parameter, "start", "The initial date of the copyright", this::getStart), - new DescriptionImpl(Type.Parameter, "stop", "The last date the copyright we modifed", this::getStop), - new DescriptionImpl(Type.Parameter, "owner", "The owner of the copyright", this::getOwner), }; + private final String start; + private final String stop; + private final String owner; /** * Constructs the CopyrightMatcher with the specified start, stop and owner strings and a unique random id.. @@ -112,15 +115,18 @@ public CopyrightMatcher(String id, String start, String stop, String owner) { } } - private String getStart() { + @ConfigComponent(type=Component.Type.Parameter, name="start", desc="The initial date of the copyright") + public String getStart() { return start; } - private String getStop() { + @ConfigComponent(type=Component.Type.Parameter, name="stop", desc="The last date the copyright we modifed") + public String getStop() { return stop; } - private String getOwner() { + @ConfigComponent(type=Component.Type.Parameter, name="owner", desc="The owner of the copyright") + public String getOwner() { return owner; } @@ -143,11 +149,4 @@ public boolean matches(IHeaders headers) { } return false; } - - - @Override - public Description getDescription() { - return new IHeaderMatcher.MatcherDescription(this, "copyright", "Matches copyright statements") - .addChildren(children); - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java index 14ca6ebff..e741fe7b0 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java @@ -18,13 +18,19 @@ */ package org.apache.rat.analysis.matchers; +import java.util.List; import java.util.Objects; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigChildren; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; import org.apache.rat.analysis.IHeaders; /** * An IHeaderMatcher that reverses the result of an enclosed matcher. */ +@ConfigComponent(type=Component.Type.Matcher, name="not", desc="Negates the enclosed matcher.") public class NotMatcher extends AbstractHeaderMatcher { private final IHeaderMatcher enclosed; @@ -49,6 +55,11 @@ public NotMatcher(String id, IHeaderMatcher enclosed) { Objects.requireNonNull(enclosed, "enclosed matcher may not be null"); this.enclosed = enclosed; } + + @ConfigChildren(parameterType=IHeaderMatcher.class) + public List getEnclosed() { + return Arrays.asList(enclosed); + } @Override public boolean matches(IHeaders headers) { diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java index a7671eee3..682d49422 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java @@ -22,10 +22,14 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; /** * A matcher that performs a logical {@code OR} across all the contained matchers. */ +@ConfigComponent(type=Component.Type.Matcher, name="or", desc="Returns true if at least one of the enclosed matchers return true.") public class OrMatcher extends AbstractMatcherContainer { /** diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java index e13ca58f6..81c58e6a3 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java @@ -28,6 +28,9 @@ import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; /** * Defines a factory to produce matchers for an SPDX tag. SPDX tag is of the format @@ -76,7 +79,7 @@ private SPDXMatcherFactory() { * @param spdxId the spdx name to match. * @return a spdx matcher. */ - public IHeaderMatcher create(String spdxId) { + public Match create(String spdxId) { if (StringUtils.isBlank(spdxId)) { throw new ConfigurationException("'spdx' type matcher requires a name"); } @@ -111,9 +114,16 @@ private boolean check(String line, Match caller) { return (lastMatch != null) && caller.spdxId.equals(lastMatch.spdxId); } + @ConfigComponent(type=Component.Type.Matcher, name="spdx", desc="Matches SPDX enclosed license identifier.") public class Match extends AbstractSimpleMatcher { String spdxId; + + @ConfigComponent(type=Component.Type.Text, name="", desc="") + public String getSpdx() { + return spdxId; + } + /** * Constructor. * @@ -137,11 +147,5 @@ public void reset() { SPDXMatcherFactory.this.lastMatch = null; } - - @Override - public Description getDescription() { - return new IHeaderMatcher.MatcherDescription(this, "spdx", "Matches SPDX license identifier in the text") - .addChildren(children); - } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index b9b393d2b..8b2590bcc 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -21,19 +21,19 @@ import java.util.regex.Pattern; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.config.parameters.DescriptionImpl; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; import org.apache.rat.analysis.IHeaders; /** * A simple regular expression matching IHeaderMatcher */ +@ConfigComponent(type=Component.Type.Matcher, name="regex", desc="Performs a regex match using the enclosed the text") public class SimpleRegexMatcher extends AbstractSimpleMatcher { private final Pattern pattern; - private Description[] children = { - new DescriptionImpl(Type.Text, "", "The regex pattern to match", this::getPattern) }; - /** * Constructs a regex pattern matcher with a unique random id and the specified * Regex pattern. @@ -58,6 +58,7 @@ public SimpleRegexMatcher(String id, Pattern pattern) { this.pattern = pattern; } + @ConfigComponent(type=Component.Type.Text, name="", desc="") private String getPattern() { return pattern.pattern(); } @@ -66,10 +67,4 @@ private String getPattern() { public boolean matches(IHeaders headers) { return pattern.matcher(headers.raw()).find(); } - - @Override - public Description getDescription() { - return new IHeaderMatcher.MatcherDescription(this, "regex", "Performs a regex match on the text") - .addChildren(children); - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java index 4e29b3306..6dac7e2e2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java @@ -21,50 +21,51 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.config.parameters.DescriptionImpl; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigChildren; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.ConfigParameter; +import org.apache.rat.config.parameters.Description; /** * A simple text matching IHeaderMatcher implementation. */ +@ConfigComponent(type=Component.Type.Matcher, name="text", desc="Matches the enclosed the text") public class SimpleTextMatcher extends AbstractSimpleMatcher { - private final String pattern; - - private Description[] children = { new DescriptionImpl(Type.Text, "", "The text to match", this::getSimpleText) }; + private final String simpleText; /** * Constructs the simple text matcher for the simple string. * * @param pattern The pattern to match. Will only match a single line from the input stream. */ - public SimpleTextMatcher(String pattern) { - this(null, pattern); + public SimpleTextMatcher(String simpleText) { + this(null, simpleText); } /** * Constructs the simple text matcher for the simple string. * * @param id The id for this matcher. - * @param pattern The pattern to match. Will only match a single line from the input stream. + * @param simpleText The pattern to match. Will only match a single line from the + * input stream. */ - public SimpleTextMatcher(String id, String pattern) { + public SimpleTextMatcher(String id, String simpleText) { super(id); - if (StringUtils.isBlank(pattern)) { - throw new IllegalArgumentException("Pattern may not be null, empty or blank"); + if (StringUtils.isBlank(simpleText)) { + throw new IllegalArgumentException("Simple text may not be null, empty or blank"); } - this.pattern = pattern; + this.simpleText = simpleText; } - private String getSimpleText() { - return this.pattern; + @ConfigComponent(type=Component.Type.Text, name="", desc="") + public String getSimpleText() { + return this.simpleText; } @Override public boolean matches(IHeaders headers) { - return headers.raw().contains(pattern); + return headers.raw().contains(simpleText); } - @Override - public Description getDescription() { - return new IHeaderMatcher.MatcherDescription(this, "text", "Matches text statement").addChildren(children); - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java index 9ada3733d..f2dba8c9d 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java @@ -1,10 +1,5 @@ package org.apache.rat.config.parameters; -import java.util.Collection; -import java.util.Collections; -import java.util.stream.Collectors; - - public interface Component { public enum Type { License, Matcher, Parameter, Text }; @@ -12,45 +7,8 @@ public enum Type { License, Matcher, Parameter, Text }; * Returns the component Description. * @return the component description. */ - Description getDescription(); - - interface Description { - public Type getType(); - - /** - * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) - * @return The common name for the item being inspected. - */ - String getCommonName(); - - /** - * Gets the description of descriptive text for the component. - * @return the descriptive text; - */ - String getDescription(); - - /** - * Gets the string parameter value if this inspector has no - * @return the string value (default returns an empty string. - */ - String getParamValue(); - - /** - * Gets a map of the parameters that the object contains. For example Copyright has 'start', 'stop', and 'owner' - * parameters. Some IHeaderMatchers have simple text values (e.g. 'regex' or 'text' types) these should list - * an unnamed parameter (empty string) with the text value. - * @return the map of parameters to the objects that represent them. - */ - default Collection getChildren() { return Collections.emptyList(); } - - /** - * Get all the children of a specific type - * @param type the type to return - * @return the collection of children of the specified type. - */ - default Collection childrenOfType(Type type) { - return getChildren().stream().filter(i -> i.getType() == type).collect(Collectors.toList()); - } + default Description getDescription() { + return DescriptionBuilder.build(this); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java new file mode 100644 index 000000000..2c6ac630f --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java @@ -0,0 +1,11 @@ +package org.apache.rat.config.parameters; + + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ConfigChildren { + String name() default ""; + Class parameterType() default String.class; +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java new file mode 100644 index 000000000..77d504602 --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java @@ -0,0 +1,23 @@ +package org.apache.rat.config.parameters; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ConfigComponent { + /** + * The common name for the component. + */ + String name(); + + /** + * The description of the component. + */ + String desc(); + /** + * The component type + */ + Component.Type type(); + + Class parameterType() default String.class; +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java new file mode 100644 index 000000000..1431b1dbe --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java @@ -0,0 +1,12 @@ +package org.apache.rat.config.parameters; + +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Retention(RetentionPolicy.RUNTIME) +public @interface ConfigParameter { + /** + * The name of the parameter variable if not same as java variable. + */ + String name() default ""; +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java new file mode 100644 index 000000000..dea0b32b6 --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java @@ -0,0 +1,71 @@ +package org.apache.rat.config.parameters; + +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.TreeMap; +import java.util.stream.Collectors; + +import org.apache.rat.config.parameters.Component.Type; + +final public class Description { + + final Type type; + final String name; + final String desc; + final String value; + final Map children; + + public Description(Type type, String name, String desc, String value, Collection children) { + this.type = type; + this.name = name; + this.desc = desc; + this.value = value; + this.children = new TreeMap<>(); + if (children != null) { + children.forEach(d -> {this.children.put(d.name, d);}); + } + } + /** + * Gets the type of the object this description decribes. + * @return the obhect type. + */ + public Type getType() { return type; } + + /** + * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) + * May not be null. + * @return The common name for the item being inspected. + */ + public String getCommonName() { return name; } + + /** + * Gets the description of descriptive text for the component. + * May be an empty string or null. + * @return the descriptive text; + */ + public String getDescription() { return desc;} + + /** + * Gets the string parameter value. if this description has no value it should return null. + * @return the string value (default returns an empty string. + */ + public String getParamValue() { return value; }; + + /** + * Gets a map of the parameters that the object contains. For example Copyright has 'start', 'stop', and 'owner' + * parameters. Some IHeaderMatchers have simple text values (e.g. 'regex' or 'text' types) these should list + * an unnamed parameter (empty string) with the text value. + * @return the map of parameters to the objects that represent them. + */ + public Map getChildren() { return children; }; + + /** + * Get all the children of a specific type + * @param type the type to return + * @return the collection of children of the specified type. + */ + public Collection childrenOfType(Type type) { + return children.values().stream().filter(d -> d.type == type).collect(Collectors.toList()); + } +} \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java new file mode 100644 index 000000000..8281fae46 --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java @@ -0,0 +1,89 @@ +package org.apache.rat.config.parameters; + +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; +import java.util.ArrayList; +import java.util.Objects; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.license.ILicense; + +public class DescriptionBuilder { + + public static Description build(Object obj) { + ConfigComponent configComponent = obj.getClass().getAnnotation(ConfigComponent.class); + if (configComponent == null) { + if (obj instanceof ILicense) { + return build((ILicense) obj); + } + return null; + } + + Optional configChildren = Arrays.stream(obj.getClass().getMethods()) + .filter(m -> Objects.nonNull(m.getAnnotation(ConfigChildren.class))).findFirst(); + List configParams = Arrays.stream(obj.getClass().getMethods()) + .filter(m -> Objects.nonNull(m.getAnnotation(ConfigComponent.class))).collect(Collectors.toList()); + + List children = configParams.stream().map(m -> DescriptionBuilder.build(obj, m)) + .filter(Objects::nonNull).collect(Collectors.toList()); + if (configChildren.isPresent()) { + Method m = configChildren.get(); + try { + Object childrenObj = m.invoke(obj); + if (childrenObj instanceof Iterable) { + for (Object o : (Iterable) childrenObj) { + Description childDesc = DescriptionBuilder.build(o); + if (childDesc != null) { + children.add(childDesc); + } + } + } else { + Description childDesc = DescriptionBuilder.build(childrenObj); + if (childDesc != null) { + children.add(childDesc); + } + } + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + } + + return new Description(configComponent.type(), configComponent.name(), configComponent.desc(), null, children); + } + + public static Description build(Object obj, Method m) { + ConfigComponent configComponent = m.getAnnotation(ConfigComponent.class); + if (configComponent == null) { + return null; + } + + String value = null; + try { + Object o = m.invoke(obj); + value = o == null ? null : o.toString(); + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { + // TODO Auto-generated catch block + e.printStackTrace(); + } + return new Description(configComponent.type(), configComponent.name(), configComponent.desc(), value, + Collections.emptyList()); + } + + public static Description build(ILicense license) { + IHeaderMatcher matcher = license.getMatcher(); + List children = new ArrayList<>(); + children.add( new Description(Component.Type.Parameter, "id", "The ID for this license", license.getId(), null)); + children.add( new Description(Component.Type.Parameter, "name", "The name for this license", license.getName(), null)); + children.add( new Description(Component.Type.Parameter, "notes", "The notes for this license", license.getNotes(), null)); + if (matcher != null) { + children.add(DescriptionBuilder.build(matcher)); + } + return new Description(Component.Type.License, license.getName(), "", null, children); + } +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java deleted file mode 100644 index 6e9c42af2..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionImpl.java +++ /dev/null @@ -1,39 +0,0 @@ -package org.apache.rat.config.parameters; - -import java.util.function.Supplier; - -import org.apache.rat.config.parameters.Component.Type; - -public class DescriptionImpl implements Component.Description { - private final Type type; - private final String name; - private final String desc; - private final Supplier getter; - - public DescriptionImpl(Type type, String name, String desc, Supplier getter) { - this.type = type; - this.name = name; - this.desc = desc; - this.getter = getter == null ? () -> "" : getter;; - } - - @Override - public Type getType() { - return type; - } - - @Override - public String getCommonName() { - return name; - } - - @Override - public String getDescription() { - return desc; - } - - @Override - public String getParamValue() { - return getter.get(); - } -} diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java index 82fc8af44..0355d0502 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/MatcherBuilderTracker.java @@ -103,7 +103,6 @@ private void addBuilderImpl(String className, String name) { if (AbstractBuilder.class.isAssignableFrom(clazz)) { @SuppressWarnings("unchecked") Class candidate = (Class) clazz; - // String name = attributes.get(AttributeName.name); if (StringUtils.isBlank(name)) { name = candidate.getSimpleName(); if (!name.endsWith("Builder")) { 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 eb23dec2b..f6979e8df 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 @@ -142,7 +142,7 @@ public void addLicenses(URL url) { } /** - * Read the urls and create a single document to process. + * Read the urls and extract the DOM information to create new objects. * * @param urls The URLs to read. */ diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java index 9c0980e5f..debeda69c 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java @@ -27,7 +27,7 @@ public class AllBuilder extends ChildContainerBuilder { @Override - public IHeaderMatcher build() { + public AndMatcher build() { return new AndMatcher(getId(), getChildren()); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java index 6ecb73e97..6ae1952f4 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java @@ -27,7 +27,7 @@ public class AnyBuilder extends ChildContainerBuilder { @Override - public IHeaderMatcher build() { + public OrMatcher build() { return new OrMatcher(getId(), getChildren()); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java index 61e264b8b..a3967f490 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java @@ -28,7 +28,7 @@ public class NotBuilder extends ChildContainerBuilder { @Override - public IHeaderMatcher build() { + public NotMatcher build() { if (children.size() != 1) { throw new ConfigurationException("'not' type matcher requires one and only one enclosed matcher"); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java index a132ba6c6..db90ea1e2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java @@ -45,7 +45,7 @@ public RegexBuilder setExpr(String exp) { } @Override - public IHeaderMatcher build() { + public SimpleRegexMatcher build() { if (null == pattern) { throw new ConfigurationException("'regex' type matcher requires an expression"); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java index a65f08259..fd572bcc8 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java @@ -42,7 +42,7 @@ public SpdxBuilder setName(String name) { } @Override - public IHeaderMatcher build() { + public SPDXMatcherFactory.Match build() { return SPDXMatcherFactory.INSTANCE.create(name); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java index 456afe03b..45d00531f 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java @@ -42,7 +42,7 @@ public TextBuilder setText(String text) { } @Override - public IHeaderMatcher build() { + public SimpleTextMatcher build() { if (StringUtils.isBlank(text)) { throw new ConfigurationException("text value is required"); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java index 2f917bfa2..7a002ab6b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java @@ -28,7 +28,8 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.DescriptionImpl; +import org.apache.rat.config.parameters.ConfigComponent; +import org.apache.rat.config.parameters.Description; /** * The definition of a License. @@ -42,19 +43,23 @@ public interface ILicense extends IHeaderMatcher, Comparable, Componen /** * @return the notes associated with this license. May be null or empty. */ + @ConfigComponent(type=Component.Type.Parameter, name="notes", desc="Any notes related to this license.") String getNotes(); - /** - * @return the id of a license that this license is derived from. May be null. - */ - String derivedFrom(); - /** * Returns the name of this license. If no name was specified then the name of * the family is returned. * @return the name of this license. */ + @ConfigComponent(type=Component.Type.Parameter, name="name", desc="The name of this license.") String getName(); + + @ConfigComponent(type=Component.Type.Parameter, name="family", desc="The family this license belongs to.") + default String getFamilyName() { + return getLicenseFamily().getFamilyName(); + } + + IHeaderMatcher getMatcher(); /** * @return An ILicense.Builder instance. @@ -70,33 +75,6 @@ static Comparator getComparator() { return Comparator.comparing(IHeaderMatcher::getId); } - class ILicenseDescription extends DescriptionImpl { - private ILicense self; - private IHeaderMatcher matcher; - - Description[] children = { - new DescriptionImpl(Type.Parameter, "name", "The name of this license", () -> self.getName()), - new DescriptionImpl(Type.Parameter, "id", "The id of this license", () -> self.getId()), - new DescriptionImpl(Type.Parameter, "family", "The family this license belongs to", - () -> self.getLicenseFamily().getFamilyCategory()), - new DescriptionImpl(Type.Parameter, "notes", "Any notes related to this family", () -> self.getNotes()), }; - - public ILicenseDescription(ILicense license, IHeaderMatcher matcher) { - super(Type.License, "license", "A license definition", null); - self = license; - this.matcher = matcher; - } - - @Override - public Collection getChildren() { - List result = new ArrayList<>(); - result.addAll(Arrays.asList(children)); - result.add(matcher.getDescription()); - return result; - } - - } - /** * A builder for ILicense instances. */ 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 d32a99b11..4d44d0bcc 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 @@ -25,6 +25,9 @@ import org.apache.rat.analysis.IHeaders; +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Description; + /** * Class to take a set of ILicenses and collection of approved license * categories and extract Subsets. @@ -187,21 +190,22 @@ public ILicenseFamily getLicenseFamily() { public String getNotes() { return null; } - + @Override - public String derivedFrom() { - return null; + public String getName() { + return searchFamily.getFamilyName(); } @Override - public String getName() { - return searchFamily.getFamilyName(); + public IHeaderMatcher getMatcher() { + return null; } @Override public Description getDescription() { return new ILicenseDescription(this, null); } + }; return search(target, licenses); } 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 b14aa1f1b..d5055d94d 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 @@ -23,6 +23,7 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.IHeaders; +import org.apache.rat.config.parameters.ConfigChildren; /** * A simple implementation of ILicense. @@ -61,6 +62,8 @@ public void setFamily(ILicenseFamily family) { this.family = family; } + @Override + @ConfigChildren public IHeaderMatcher getMatcher() { return matcher; } @@ -103,18 +106,8 @@ public String getNotes() { return notes; } - @Override - public String derivedFrom() { - return derivedFrom; - } - @Override public String getName() { return name; } - - @Override - public Description getDescription() { - return new ILicense.ILicenseDescription(this, matcher); - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java index 519c7b3e1..c6b05874e 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -21,18 +21,22 @@ import java.io.IOException; import java.util.Collection; import java.util.HashSet; +import java.util.Map; +import java.util.TreeMap; import java.util.Optional; import java.util.Set; import java.util.SortedSet; import java.util.UUID; +import org.apache.commons.lang3.StringUtils; import org.apache.rat.ReportConfiguration; import org.apache.rat.api.RatException; -import org.apache.rat.config.parameters.Component.Description; import org.apache.rat.config.parameters.Component.Type; +import org.apache.rat.config.parameters.Description; import org.apache.rat.configuration.MatcherBuilderTracker; import org.apache.rat.configuration.XMLConfigurationReader; import org.apache.rat.configuration.builders.MatcherRefBuilder; +import org.apache.rat.configuration.builders.MatcherRefBuilder.IHeaderMatcherProxy; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; @@ -117,6 +121,13 @@ private void writeDescriptions(Collection descriptions) throws RatE } } + private void writeChildren(Description description) throws RatException, IOException { + writeDescriptions(description.childrenOfType(Type.Parameter)); + writeDescriptions(description.childrenOfType(Type.Text)); + writeDescriptions(description.childrenOfType(Type.Matcher)); + writeDescriptions(description.childrenOfType(Type.License)); + } + private void writeDescription(Description description) throws RatException { if (description == null) { return; @@ -125,24 +136,25 @@ private void writeDescription(Description description) throws RatException { switch (description.getType()) { case Matcher: // see if id was registered - Optional id = description.getChildren().stream().filter( - i -> i.getType() == Type.Parameter && XMLConfigurationReader.ATT_ID.equals(i.getCommonName())) - .findFirst(); + Optional id = description.childrenOfType(Type.Parameter).stream().filter(i -> XMLConfigurationReader.ATT_ID.equals(i.getCommonName())).findFirst(); if (id.isPresent()) { String idStr = id.get().getParamValue(); if (matchers.contains(idStr)) { - writer.openElement("matcherRef").attribute(MatcherRefBuilder.ATT_REF_ID, idStr).closeElement(); - return; + description = new MatcherRefBuilder.IHeaderMatcherProxy(id.get().getParamValue(),null).getDescription(); + } else { + matchers.add(idStr); } - matchers.add(idStr); + } + if (StringUtils.isNotBlank(description.getDescription())) { + writer.comment(description.getDescription()); } writer.openElement(description.getCommonName()); - writeDescriptions(description.getChildren()); + writeChildren(description); writer.closeElement(); break; - case License: + case License: writer.openElement(XMLConfigurationReader.LICENSE); - writeDescriptions(description.getChildren()); + writeChildren(description); writer.closeElement(); break; case Parameter: diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java index 144ee2e32..f41baa344 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/IXmlWriter.java @@ -49,6 +49,16 @@ public interface IXmlWriter extends AutoCloseable { */ IXmlWriter openElement(CharSequence elementName) throws IOException; + /** + * Writes a comment + * + * @param text the comment text + * @return this object + * @throws OperationNotAllowedException + * if called after the first element has been closed + */ + IXmlWriter comment(CharSequence text) throws IOException; + /** * Writes an attribute of an element. * Note that this is only allowed directly after {@link #openElement(CharSequence)} diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java index b11116628..8658a79e4 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/impl/base/XmlWriter.java @@ -469,6 +469,18 @@ public IXmlWriter openElement(final CharSequence elementName) throws IOException currentAttributes.clear(); return this; } + + @Override + public IXmlWriter comment(final CharSequence text) throws IOException { + if (inElement) { + writer.write('>'); + } + inElement = false; + writer.write(""); + return this; + } /** * Writes an attribute of an element. Note that this is only allowed directly diff --git a/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java new file mode 100644 index 000000000..4f2848f23 --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java @@ -0,0 +1,33 @@ +package org.apache.rat.license; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.util.Map; + +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.testhelpers.TestingMatcher; +import org.junit.jupiter.api.Test; + +public class SimpleLicenseTest { + + @Test + public void descriptionTest() { + SimpleLicense lic = new SimpleLicense( + ILicenseFamily.builder().setLicenseFamilyCategory("familyId") + .setLicenseFamilyName("TestingLicense: familyId").build(), + new TestingMatcher(), "derived from", "These are the notes", "My testing license", "TestingId"); + Description underTest = lic.getDescription(); + assertEquals(Component.Type.License, underTest.getType()); + assertEquals("My testing license", underTest.getCommonName()); + assertEquals("", underTest.getDescription()); + assertNull(underTest.getParamValue()); + Map children = underTest.getChildren(); + assertTrue(children.containsKey("id")); + assertTrue(children.containsKey("name")); + assertTrue(children.containsKey("notes")); + assertTrue(children.containsKey("TestingMatcher")); + } +} diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java index 96e39ab14..de3de2b4c 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java +++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingLicense.java @@ -20,7 +20,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaders; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; @@ -37,14 +36,14 @@ public class TestingLicense implements ILicense { private String id; /** - * Creates a testing license named "DfltTst" with category of "DfltT" and a default - * TestingMatcher. + * Creates a testing license named "DfltTst" with category of "DfltT" and a + * default TestingMatcher. * @see TestingMatcher */ public TestingLicense() { this("DfltTst", new TestingMatcher()); } - + /** * Creates a testing license with the specified id and a default TestingMatcher * @param id The ID to use. @@ -63,7 +62,7 @@ public TestingLicense(String id, IHeaderMatcher matcher) { this(matcher, ILicenseFamily.builder().setLicenseFamilyCategory(id) .setLicenseFamilyName("TestingLicense: " + id).build()); } - + /** * Creates a testing license with the specified matcher and family. * @param matcher the matcher to use. @@ -75,14 +74,15 @@ public TestingLicense(IHeaderMatcher matcher, ILicenseFamily family) { this.derivedFrom = null; this.notes = null; } - + /** - * Create a testing license for the specified family using a default TestingMatcher + * Create a testing license for the specified family using a default + * TestingMatcher * @param family the family for the license. * @see TestingMatcher */ public TestingLicense(ILicenseFamily family) { - this(new TestingMatcher(), family ); + this(new TestingMatcher(), family); } @Override @@ -91,7 +91,7 @@ public String toString() { } /** - * Gets the family from the license + * Gets the family from the license * @return the license family. */ public ILicenseFamily getFamily() { @@ -102,6 +102,7 @@ public ILicenseFamily getFamily() { * Gets the matcher from the license * @return the matcher. */ + @Override public IHeaderMatcher getMatcher() { return matcher; } @@ -113,7 +114,7 @@ public IHeaderMatcher getMatcher() { public void setDerivedFrom(String derivedFrom) { this.derivedFrom = derivedFrom; } - + /** * Sets the name from value for this license. * @param name the name of this license. @@ -125,6 +126,7 @@ public void setName(String name) { public void setId(String id) { this.id = id; } + @Override public String getId() { return StringUtils.defaultIfBlank(id, family.getFamilyCategory().trim()); @@ -136,8 +138,18 @@ public void reset() { } @Override - public boolean matches(IHeaders headers) { - return matcher.matches(headers); + public State matches(String line) { + return matcher.matches(line); + } + + @Override + public State finalizeState() { + return matcher.finalizeState(); + } + + @Override + public State currentState() { + return matcher.currentState(); } @Override @@ -159,15 +171,4 @@ public String getNotes() { public String getName() { return StringUtils.defaultIfBlank(name, family.getFamilyName()); } - - @Override - public String derivedFrom() { - return derivedFrom; - } - - @Override - public Description getDescription() { - return new ILicense.ILicenseDescription(this, matcher); - } - } diff --git a/apache-rat-tasks/src/test/java/org/example/Matcher.java b/apache-rat-tasks/src/test/java/org/example/Matcher.java index 392f42321..d5166d24a 100644 --- a/apache-rat-tasks/src/test/java/org/example/Matcher.java +++ b/apache-rat-tasks/src/test/java/org/example/Matcher.java @@ -18,8 +18,7 @@ import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.matchers.AbstractSimpleMatcher; -import org.apache.rat.inspector.AbstractInspector; -import org.apache.rat.inspector.Inspector; +import org.apache.rat.config.parameters.Description; public class Matcher extends AbstractSimpleMatcher { public Matcher() { From 4d2e2cfd9af3d72ffb280dc3563ef96f49913b8b Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Fri, 22 Mar 2024 10:43:23 +0100 Subject: [PATCH 24/77] adding missed changes --- .../org/apache/rat/analysis/matchers/SimpleRegexMatcher.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index 8b2590bcc..9a197702a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -58,7 +58,7 @@ public SimpleRegexMatcher(String id, Pattern pattern) { this.pattern = pattern; } - @ConfigComponent(type=Component.Type.Text, name="", desc="") + @ConfigComponent(type=Component.Type.Text, name="", desc="", parameterType=Pattern.class) private String getPattern() { return pattern.pattern(); } From 058bb705b4cd720c20c09f702e35da79f9f49520 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 24 Mar 2024 09:26:10 +0100 Subject: [PATCH 25/77] changes for readind xml --- .../config/parameters/ConfigComponent.java | 1 + .../configuration/XMLConfigurationReader.java | 4 ++-- .../java/org/apache/rat/license/ILicense.java | 15 +------------- .../org/apache/rat/license/SimpleLicense.java | 9 ++------- .../rat/report/ConfigurationReport.java | 20 ++++++++++++++++++- 5 files changed, 25 insertions(+), 24 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java index 77d504602..0f1be1989 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java @@ -2,6 +2,7 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; @Retention(RetentionPolicy.RUNTIME) public @interface ConfigComponent { 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 f6979e8df..66f6b3531 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 @@ -38,6 +38,7 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.FullTextMatcher; import org.apache.rat.analysis.matchers.SimpleTextMatcher; +import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.configuration.builders.AbstractBuilder; import org.apache.rat.configuration.builders.ChildContainerBuilder; import org.apache.rat.configuration.builders.MatcherRefBuilder; @@ -85,7 +86,6 @@ public class XMLConfigurationReader implements LicenseReader, MatcherReader { public final static String ATT_ID = "id"; public final static String ATT_NAME = "name"; - private final static String ATT_DERIVED_FROM = "derived_from"; public final static String ATT_LICENSE_REF = "license_ref"; public final static String ATT_CLASS_NAME = "class"; @@ -271,6 +271,7 @@ public IHeaderMatcher build() { private ILicense parseLicense(Node licenseNode) { Map attributes = attributes(licenseNode); ILicense.Builder builder = ILicense.builder(); + Description desc = DescriptionBuilder.build(null) builder.setLicenseFamilyCategory(attributes.get(FAMILY)); builder.setName(attributes.get(ATT_NAME)); @@ -286,7 +287,6 @@ private ILicense parseLicense(Node licenseNode) { } } }); - builder.setDerivedFrom(StringUtils.defaultIfBlank(attributes.get(ATT_DERIVED_FROM), null)); builder.setNotes(StringUtils.defaultIfBlank(notesBuilder.toString().trim(), null)); return builder.build(licenseFamilies); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java index 7a002ab6b..c62f4ef81 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java @@ -84,8 +84,6 @@ class Builder { private String notes; - private String derivedFrom; - private String name; private String id; @@ -134,17 +132,6 @@ public Builder setId(String id) { return this; } - /** - * Sets the derived from fields in the license. - * @param derivedFrom the family category of the license this license was - * derived from. - * @return this builder for chaining. - */ - public Builder setDerivedFrom(String derivedFrom) { - this.derivedFrom = derivedFrom; - return this; - } - /** * Set the family category for this license. The category must be unique across * all licenses and must be 5 characters. If more than 5 characters are provided @@ -178,7 +165,7 @@ public ILicense build(SortedSet licenseFamilies) { Objects.requireNonNull(matcher, "Matcher must not be null"); ILicenseFamily family = LicenseFamilySetFactory.search(licenseFamily.build(), licenseFamilies); Objects.requireNonNull(family, "License family " + licenseFamily.getCategory() + " not found."); - return new SimpleLicense(family, matcher.build(), derivedFrom, notes, name, id); + return new SimpleLicense(family, matcher.build(), notes, name, id); } } } 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 d5055d94d..d6cc742c5 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 @@ -32,18 +32,17 @@ class SimpleLicense implements ILicense { private ILicenseFamily family; private IHeaderMatcher matcher; - private String derivedFrom; + private String notes; private String name; private String id; - SimpleLicense(ILicenseFamily family, IHeaderMatcher matcher, String derivedFrom, String notes, String name, + SimpleLicense(ILicenseFamily family, IHeaderMatcher matcher, String notes, String name, String id) { Objects.requireNonNull(matcher, "Matcher must not be null"); Objects.requireNonNull(family, "Family must not be null"); this.family = family; this.matcher = matcher; - this.derivedFrom = derivedFrom; this.notes = notes; this.name = StringUtils.defaultIfBlank(name, family.getFamilyName()); this.id = StringUtils.defaultIfBlank(id, family.getFamilyCategory().trim()); @@ -72,10 +71,6 @@ public void setMatcher(IHeaderMatcher matcher) { this.matcher = matcher; } - public void setDerivedFrom(String derivedFrom) { - this.derivedFrom = derivedFrom; - } - @Override public String getId() { return id; diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java index c6b05874e..9b02fd9d5 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -21,12 +21,14 @@ import java.io.IOException; import java.util.Collection; import java.util.HashSet; +import java.util.List; import java.util.Map; import java.util.TreeMap; import java.util.Optional; import java.util.Set; import java.util.SortedSet; import java.util.UUID; +import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; import org.apache.rat.ReportConfiguration; @@ -120,7 +122,7 @@ private void writeDescriptions(Collection descriptions) throws RatE writeDescription(description); } } - + private void writeChildren(Description description) throws RatException, IOException { writeDescriptions(description.childrenOfType(Type.Parameter)); writeDescriptions(description.childrenOfType(Type.Text)); @@ -154,6 +156,22 @@ private void writeDescription(Description description) throws RatException { break; case License: writer.openElement(XMLConfigurationReader.LICENSE); + List lst = description.childrenOfType(Type.Parameter).stream().filter(d -> !d.getCommonName().equals("notes")).collect(Collectors.toList()); + writeDescriptions(lst); + + lst = description.childrenOfType(Type.Parameter).stream().filter(d -> !d.getCommonName().equals("notes")).collect(Collectors.toList()); + if (!lst.isEmpty()) { + if (StringUtils.isNotBlank(lst.get(0).getDescription())) { + writer.comment(lst.get(0).getDescription()); + } + for (Description note : lst) { + writer.openElement(note.getCommonName()); + writer.content(description.getParamValue()); + writer.closeElement(); + } + } + writeDescriptions(description.childrenOfType(Type.Matcher)); + writeDescriptions(description.childrenOfType(Type.License)); writeChildren(description); writer.closeElement(); break; From 746bf87ff031d9e6324070c0e2a627c2ceaff51e Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Sun, 24 Mar 2024 09:23:45 +0100 Subject: [PATCH 26/77] modified to build description map --- .../apache/rat/analysis/IHeaderMatcher.java | 11 ++- .../analysis/matchers/SimpleTextMatcher.java | 24 +++---- .../config/parameters/ConfigParameter.java | 12 ---- .../rat/config/parameters/Description.java | 7 +- .../config/parameters/DescriptionBuilder.java | 70 +++++++++++++------ .../builders/AbstractBuilder.java | 6 +- .../java/org/apache/rat/license/ILicense.java | 2 + .../ConfigurationReaderTest.java | 21 ++++++ 8 files changed, 103 insertions(+), 50 deletions(-) delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java index 351338509..1dc779bae 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java @@ -18,6 +18,7 @@ */ package org.apache.rat.analysis; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -25,6 +26,7 @@ import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.configuration.builders.AllBuilder; import org.apache.rat.configuration.builders.AnyBuilder; import org.apache.rat.configuration.builders.CopyrightBuilder; @@ -46,7 +48,7 @@ public interface IHeaderMatcher extends Component { * * @return the Identifier for this matcher. */ - @ConfigComponent(type=Component.Type.Parameter, name="id", desc="The id of this matcher.") + @ConfigComponent(type=Component.Type.Parameter, name="id", desc="The id of this component.") String getId(); /** @@ -74,7 +76,12 @@ interface Builder { * @return a new IHeaderMatcher. */ IHeaderMatcher build(); - + + default Description getDescription() throws NoSuchMethodException, SecurityException { + Method m = this.getClass().getMethod("build"); + return DescriptionBuilder.buildMap(m.getReturnType()); + } + /** * @return an instance of the standard TextBuilder. * @see TextBuilder diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java index 6dac7e2e2..91b00e410 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java @@ -19,25 +19,21 @@ package org.apache.rat.analysis.matchers; import org.apache.commons.lang3.StringUtils; -import org.apache.rat.analysis.IHeaders; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.ConfigChildren; import org.apache.rat.config.parameters.ConfigComponent; -import org.apache.rat.config.parameters.ConfigParameter; -import org.apache.rat.config.parameters.Description; /** * A simple text matching IHeaderMatcher implementation. */ -@ConfigComponent(type=Component.Type.Matcher, name="text", desc="Matches the enclosed the text") +@ConfigComponent(type = Component.Type.Matcher, name = "text", desc = "Matches the enclosed the text") public class SimpleTextMatcher extends AbstractSimpleMatcher { private final String simpleText; /** * Constructs the simple text matcher for the simple string. - * - * @param pattern The pattern to match. Will only match a single line from the input stream. + * + * @param pattern The pattern to match. Will only match a single line from the + * input stream. */ public SimpleTextMatcher(String simpleText) { this(null, simpleText); @@ -45,10 +41,10 @@ public SimpleTextMatcher(String simpleText) { /** * Constructs the simple text matcher for the simple string. - * + * * @param id The id for this matcher. - * @param simpleText The pattern to match. Will only match a single line from the - * input stream. + * @param simpleText The pattern to match. Will only match a single line from + * the input stream. */ public SimpleTextMatcher(String id, String simpleText) { super(id); @@ -58,14 +54,14 @@ public SimpleTextMatcher(String id, String simpleText) { this.simpleText = simpleText; } - @ConfigComponent(type=Component.Type.Text, name="", desc="") + @ConfigComponent(type = Component.Type.Text, name = "", desc = "") public String getSimpleText() { return this.simpleText; } @Override - public boolean matches(IHeaders headers) { - return headers.raw().contains(simpleText); + public boolean doMatch(String line) { + return line.contains(simpleText); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java deleted file mode 100644 index 1431b1dbe..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigParameter.java +++ /dev/null @@ -1,12 +0,0 @@ -package org.apache.rat.config.parameters; - -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface ConfigParameter { - /** - * The name of the parameter variable if not same as java variable. - */ - String name() default ""; -} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java index dea0b32b6..4cde3a4e5 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java @@ -8,7 +8,7 @@ import org.apache.rat.config.parameters.Component.Type; -final public class Description { +public class Description { final Type type; final String name; @@ -26,6 +26,11 @@ public Description(Type type, String name, String desc, String value, Collection children.forEach(d -> {this.children.put(d.name, d);}); } } + + public Description(ConfigComponent configComponent, String value, Collection children) { + this(configComponent.type(), configComponent.name(), configComponent.desc(), value, children); + } + /** * Gets the type of the object this description decribes. * @return the obhect type. diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java index 8281fae46..a8ef34e46 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java @@ -3,14 +3,18 @@ import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; +import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.ArrayList; +import java.util.Map; +import java.util.TreeMap; import java.util.Objects; import java.util.Optional; import java.util.stream.Collectors; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.matchers.AbstractHeaderMatcher; import org.apache.rat.license.ILicense; public class DescriptionBuilder { @@ -18,18 +22,15 @@ public class DescriptionBuilder { public static Description build(Object obj) { ConfigComponent configComponent = obj.getClass().getAnnotation(ConfigComponent.class); if (configComponent == null) { - if (obj instanceof ILicense) { - return build((ILicense) obj); - } +// if (obj instanceof ILicense) { +// return build((ILicense) obj); +// } return null; } - Optional configChildren = Arrays.stream(obj.getClass().getMethods()) - .filter(m -> Objects.nonNull(m.getAnnotation(ConfigChildren.class))).findFirst(); - List configParams = Arrays.stream(obj.getClass().getMethods()) - .filter(m -> Objects.nonNull(m.getAnnotation(ConfigComponent.class))).collect(Collectors.toList()); + Optional configChildren = getConfigChildren(obj.getClass()); - List children = configParams.stream().map(m -> DescriptionBuilder.build(obj, m)) + List children = getConfigComponents(obj.getClass()).stream().map(m -> DescriptionBuilder.build(obj, m)) .filter(Objects::nonNull).collect(Collectors.toList()); if (configChildren.isPresent()) { Method m = configChildren.get(); @@ -54,8 +55,19 @@ public static Description build(Object obj) { } } - return new Description(configComponent.type(), configComponent.name(), configComponent.desc(), null, children); + return new Description(configComponent, null, children); + } + + private static Optional getConfigChildren(Class clazz) { + return Arrays.stream(clazz.getMethods()) + .filter(m -> Objects.nonNull(m.getAnnotation(ConfigChildren.class))).findFirst(); } + + private static List getConfigComponents(Class clazz) { + return Arrays.stream(clazz.getMethods()) + .filter(m -> Objects.nonNull(m.getAnnotation(ConfigComponent.class))).collect(Collectors.toList()); + } + public static Description build(Object obj, Method m) { ConfigComponent configComponent = m.getAnnotation(ConfigComponent.class); @@ -71,19 +83,37 @@ public static Description build(Object obj, Method m) { // TODO Auto-generated catch block e.printStackTrace(); } - return new Description(configComponent.type(), configComponent.name(), configComponent.desc(), value, - Collections.emptyList()); + return new Description(configComponent, value, Collections.emptyList()); } - public static Description build(ILicense license) { - IHeaderMatcher matcher = license.getMatcher(); - List children = new ArrayList<>(); - children.add( new Description(Component.Type.Parameter, "id", "The ID for this license", license.getId(), null)); - children.add( new Description(Component.Type.Parameter, "name", "The name for this license", license.getName(), null)); - children.add( new Description(Component.Type.Parameter, "notes", "The notes for this license", license.getNotes(), null)); - if (matcher != null) { - children.add(DescriptionBuilder.build(matcher)); +// public static Description build(ILicense license) { +// IHeaderMatcher matcher = license.getMatcher(); +// List children = new ArrayList<>(); +// for (Method m : license.getClass().getMethods()) { +// ConfigComponent config = m.getAnnotation(ConfigComponent.class); +// if (config != null) { +// Object value = m.invoke(license); +// children.add( new Description(config, value == null ? null : value.toString(), null)); +// } +// } +// if (matcher != null) { +// children.add(DescriptionBuilder.build(matcher)); +// } +// return new Description(Component.Type.License, license.getName(), "", null, children); +// } + + public static Description buildMap(Class clazz) { + ConfigComponent configComponent = clazz.getAnnotation(ConfigComponent.class); + if (configComponent == null) { + return null; } - return new Description(Component.Type.License, license.getName(), "", null, children); + List children = new ArrayList<>(); + for (Method m : clazz.getMethods()) { + ConfigComponent config = m.getAnnotation(ConfigComponent.class); + if (config != null) { + children.add(new Description(config, null, null)); + } + } + return new Description(configComponent, null, children); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java index 7d546a03a..6d105fb50 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java @@ -18,8 +18,13 @@ */ package org.apache.rat.configuration.builders; +import java.lang.reflect.Method; + import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; /** * An abstract IHeaderMatcher.Builder. @@ -62,5 +67,4 @@ protected String getId() { public String toString() { return String.format( "%s with id %s", this.getClass(), id); } - } \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java index c62f4ef81..b4909b075 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java @@ -28,6 +28,7 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigChildren; import org.apache.rat.config.parameters.ConfigComponent; import org.apache.rat.config.parameters.Description; @@ -59,6 +60,7 @@ default String getFamilyName() { return getLicenseFamily().getFamilyName(); } + @ConfigChildren IHeaderMatcher getMatcher(); /** diff --git a/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java b/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java index d1c3405f6..a73103d95 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java @@ -24,6 +24,8 @@ import java.util.Collection; import java.util.stream.Collectors; +import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Description; import org.apache.rat.configuration.builders.AbstractBuilder; import org.apache.rat.configuration.builders.AllBuilder; import org.apache.rat.configuration.builders.AnyBuilder; @@ -97,5 +99,24 @@ public void checkSystemMatcherTest() { checkMatcher("spdx", SpdxBuilder.class); checkMatcher("text", TextBuilder.class); } + + @Test + public void descriptionTest() throws NoSuchMethodException, SecurityException { + XMLConfigurationReader reader = new XMLConfigurationReader(); + URL url = ConfigurationReaderTest.class.getResource("/org/apache/rat/default.xml"); + reader.read(url); + reader.readMatcherBuilders(); + + IHeaderMatcher.Builder builder = MatcherBuilderTracker.getMatcherBuilder("copyright"); + Description desc = builder.getDescription(); + print(desc); + + } + + private void print(Description desc) { + System.out.println( String.format( "T:%s N:%s V:%s", desc.getType(), desc.getCommonName(), desc.getParamValue())); + System.out.println( " "+desc.getDescription()); + desc.getChildren().values().forEach(this::print); + } } From 8eca6cbbd43d886da2ff013dd4ef7b90c15e98bd Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Mon, 25 Mar 2024 08:41:50 +0100 Subject: [PATCH 27/77] cleanup parameter parsing --- .../apache/rat/analysis/IHeaderMatcher.java | 8 +- .../matchers/AbstractHeaderMatcher.java | 2 +- .../matchers/AbstractMatcherContainer.java | 3 +- .../analysis/matchers/CopyrightMatcher.java | 65 +++++++-------- .../rat/analysis/matchers/NotMatcher.java | 4 +- .../analysis/matchers/SPDXMatcherFactory.java | 36 ++++----- .../analysis/matchers/SimpleRegexMatcher.java | 2 +- .../analysis/matchers/SimpleTextMatcher.java | 2 +- .../rat/config/parameters/ConfigChildren.java | 15 ++-- .../config/parameters/ConfigComponent.java | 4 +- .../rat/config/parameters/Description.java | 25 ++++++ .../config/parameters/DescriptionBuilder.java | 78 +++++++----------- .../configuration/XMLConfigurationReader.java | 80 ++++++++++++------- .../builders/ChildContainerBuilder.java | 3 + .../builders/MatcherRefBuilder.java | 67 ++++++++-------- .../java/org/apache/rat/license/ILicense.java | 7 +- .../org/apache/rat/license/SimpleLicense.java | 17 ++-- .../parameters/DescriptionBuilderTest.java | 40 ++++++++++ .../ConfigurationReaderTest.java | 3 +- .../apache/rat/license/SimpleLicenseTest.java | 2 +- .../rat/report/ConfigurationReportTest.java | 1 - 21 files changed, 269 insertions(+), 195 deletions(-) create mode 100644 apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java index 1dc779bae..c352a457d 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java @@ -48,7 +48,6 @@ public interface IHeaderMatcher extends Component { * * @return the Identifier for this matcher. */ - @ConfigComponent(type=Component.Type.Parameter, name="id", desc="The id of this component.") String getId(); /** @@ -77,11 +76,10 @@ interface Builder { */ IHeaderMatcher build(); - default Description getDescription() throws NoSuchMethodException, SecurityException { - Method m = this.getClass().getMethod("build"); - return DescriptionBuilder.buildMap(m.getReturnType()); + default Class builtClass() throws NoSuchMethodException, SecurityException { + return this.getClass().getMethod("build").getReturnType(); } - + /** * @return an instance of the standard TextBuilder. * @see TextBuilder diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java index b188cd9eb..5dca0ec43 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractHeaderMatcher.java @@ -33,6 +33,7 @@ */ public abstract class AbstractHeaderMatcher implements IHeaderMatcher { + @ConfigComponent(type=Component.Type.Parameter, desc="The id of the matcher.") private final String id; /** @@ -45,7 +46,6 @@ protected AbstractHeaderMatcher(String id) { this.id = StringUtils.isBlank(id) ? UUID.randomUUID().toString() : id; } - @ConfigComponent(type=Component.Type.Parameter, name="id", desc="The id of the matcher.") @Override public String getId() { return id; diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java index b9515854c..88e6e14cb 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java @@ -25,7 +25,6 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.ConfigChildren; import org.apache.rat.config.parameters.ConfigComponent; /** @@ -34,9 +33,9 @@ */ public abstract class AbstractMatcherContainer extends AbstractHeaderMatcher { + @ConfigComponent(desc = "enclosed Matchers", type = Component.Type.Matcher) protected final Collection enclosed; - @ConfigChildren(name="enclosed") public Collection getChildren() { return enclosed; } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java index 0014c2850..a30e8c7ff 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java @@ -22,7 +22,6 @@ import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; -import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; @@ -32,26 +31,16 @@ /** * Matches a typical Copyright header line only based on a regex pattern which * allows for one (starting) year or year range, and a configurable copyright - * owner.
- *
- * The matching is done case insensitive
- *
- * Example supported Copyright header lines, using copyright owner - * "FooBar" - *
    - *
  • Copyright 2010 FooBar.
  • - *
  • Copyright 2010-2012 FooBar.
  • - *
  • copyright 2012 foobar
  • - *
- *

- * Note also that the copyright owner is appended to the regex pattern and so can - * support additional regex but also requires escaping where needed,
- * e.g. use "FooBar \\(www\\.foobar\\.com\\)" or - * "FooBar \\Q(www.foobar.com)\\E" to match "FooBar - * (www.foobar.com)" - *

- *

The matcher also accepts "(C)", "(c)", and "©" in place of (or in addition to) the "Copyright" or "copyright" - * keyword

+ * owner.

The matching is done case insensitive

Example + * supported Copyright header lines, using copyright owner "FooBar" + *
  • Copyright 2010 FooBar.
  • Copyright 2010-2012 FooBar.
  • + *
  • copyright 2012 foobar

Note also that the copyright owner + * is appended to the regex pattern and so can support additional regex but also + * requires escaping where needed,
e.g. use "FooBar + * \\(www\\.foobar\\.com\\)" or "FooBar \\Q(www.foobar.com)\\E" + * to match "FooBar (www.foobar.com)"

The matcher also + * accepts "(C)", "(c)", and "©" in place of (or in addition to) the "Copyright" + * or "copyright" keyword

*/ @ConfigComponent(type=Component.Type.Matcher, name="copyright", desc="Matches copyright statements.") public class CopyrightMatcher extends AbstractSimpleMatcher { @@ -64,15 +53,20 @@ public class CopyrightMatcher extends AbstractSimpleMatcher { private final Pattern dateOwnerPattern; private final Pattern ownerDatePattern; - + @ConfigComponent(type=Component.Type.Parameter, desc="The initial date of the copyright") private final String start; + @ConfigComponent(type=Component.Type.Parameter, desc="The last date the copyright we modifed") private final String stop; + @ConfigComponent(type=Component.Type.Parameter, name="owner", desc="The owner of the copyright") private final String owner; /** - * Constructs the CopyrightMatcher with the specified start, stop and owner strings and a unique random id.. + * Constructs the CopyrightMatcher with the specified start, stop and owner + * strings and a unique random id.. + * * @param start the start date for the copyright may be null. - * @param stop the stop date for the copyright, may be null. May not be specified if start is not specified. + * @param stop the stop date for the copyright, may be null. May not be + * specified if start is not specified. * @param owner the owner of the copyright. may be null. */ public CopyrightMatcher(String start, String stop, String owner) { @@ -80,14 +74,20 @@ public CopyrightMatcher(String start, String stop, String owner) { } /** - * Constructs the CopyrightMatcher with the specified start, stop and owner strings. + * Constructs the CopyrightMatcher with the specified start, stop and owner + * strings. + * * @param id the id for the matcher. * @param start the start date for the copyright may be null. - * @param stop the stop date for the copyright, may be null. May not be specified if start is not specified. + * @param stop the stop date for the copyright, may be null. May not be + * specified if start is not specified. * @param owner the owner of the copyright. may be null. */ public CopyrightMatcher(String id, String start, String stop, String owner) { super(id); + this.start = start; + this.stop = stop; + this.owner = owner; String dateDefn = ""; if (StringUtils.isNotEmpty(start)) { if (StringUtils.isNotEmpty(stop)) { @@ -115,28 +115,25 @@ public CopyrightMatcher(String id, String start, String stop, String owner) { } } - @ConfigComponent(type=Component.Type.Parameter, name="start", desc="The initial date of the copyright") public String getStart() { return start; } - @ConfigComponent(type=Component.Type.Parameter, name="stop", desc="The last date the copyright we modifed") public String getStop() { return stop; } - @ConfigComponent(type=Component.Type.Parameter, name="owner", desc="The owner of the copyright") public String getOwner() { return owner; } @Override - public boolean matches(IHeaders headers) { - String lowerLine = headers.raw().toLowerCase(); - if (lowerLine.contains("copyright") || lowerLine.contains("(c)") || lowerLine.contains("©")) { - Matcher matcher = COPYRIGHT_PATTERN.matcher(headers.raw()); + protected boolean doMatch(String line) { + String lowerLine = line.toLowerCase(); + if (lowerLine.contains("copyright") || lowerLine.contains("(c)") || line.contains("©")) { + Matcher matcher = COPYRIGHT_PATTERN.matcher(line); if (matcher.find()) { - String buffer = headers.raw().substring(matcher.end()); + String buffer = line.substring(matcher.end()); matcher = dateOwnerPattern.matcher(buffer); if (matcher.find() && matcher.start() == 0) { return true; diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java index e741fe7b0..ab4910531 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java @@ -23,7 +23,6 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.ConfigChildren; import org.apache.rat.config.parameters.ConfigComponent; import org.apache.rat.config.parameters.Description; import org.apache.rat.analysis.IHeaders; @@ -33,6 +32,7 @@ @ConfigComponent(type=Component.Type.Matcher, name="not", desc="Negates the enclosed matcher.") public class NotMatcher extends AbstractHeaderMatcher { + @ConfigComponent(desc = "enclosed Matcher", type=Component.Type.Matcher) private final IHeaderMatcher enclosed; /** @@ -56,7 +56,7 @@ public NotMatcher(String id, IHeaderMatcher enclosed) { this.enclosed = enclosed; } - @ConfigChildren(parameterType=IHeaderMatcher.class) + public List getEnclosed() { return Arrays.asList(enclosed); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java index 81c58e6a3..bf57b4b08 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java @@ -27,19 +27,16 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaders; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; import org.apache.rat.config.parameters.Description; /** - * Defines a factory to produce matchers for an SPDX tag. SPDX tag is of the format - * {@code SPDX-License-Identifier: short-name} where {@code short-name} matches - * the regex pattern [A-Za-z0-9\.\-]+ - *

- * SPDX identifiers are specified by the Software Package Data Exchange(R) also - * known as SPDX(R) project from the Linux foundation. - *

+ * Defines a factory to produce matchers for an SPDX tag. SPDX tag is of the + * format {@code SPDX-License-Identifier: short-name} where {@code short-name} + * matches the regex pattern [A-Za-z0-9\.\-]+

SPDX identifiers are specified + * by the Software Package Data Exchange(R) also known as SPDX(R) project from + * the Linux foundation.

* * @see List of Ids at spdx.dev */ @@ -56,7 +53,8 @@ public class SPDXMatcherFactory { public static final SPDXMatcherFactory INSTANCE = new SPDXMatcherFactory(); /** - * The regular expression to locate the SPDX license identifier in the text stream + * The regular expression to locate the SPDX license identifier in the text + * stream */ private static Pattern groupSelector = Pattern.compile(".*SPDX-License-Identifier:\\s([A-Za-z0-9\\.\\-]+)"); @@ -93,14 +91,16 @@ public Match create(String spdxId) { /** * Each matcher calls this method to present the line it is working on. - * + * * @param line The line the caller is looking at. * @param caller the Match that is calling this method. * @return true if the caller matches the text. */ private boolean check(String line, Match caller) { - // if the line has not been seen yet see if we can extract the SPDX id from the line. - // if so then see if that name has been registered. If so then we have a match and set + // if the line has not been seen yet see if we can extract the SPDX id from the + // line. + // if so then see if that name has been registered. If so then we have a match + // and set // lastMatch. if ((lastLine == null || !lastLine.equals(line)) && line.contains("SPDX-License-Identifier")) { Matcher matcher = groupSelector.matcher(line); @@ -116,10 +116,9 @@ private boolean check(String line, Match caller) { @ConfigComponent(type=Component.Type.Matcher, name="spdx", desc="Matches SPDX enclosed license identifier.") public class Match extends AbstractSimpleMatcher { - + @ConfigComponent(type=Component.Type.Text, name="spdx", desc="The spdx ID string") String spdxId; - - @ConfigComponent(type=Component.Type.Text, name="", desc="") + public String getSpdx() { return spdxId; } @@ -137,15 +136,14 @@ public String getSpdx() { } @Override - public boolean matches(IHeaders headers) { - return SPDXMatcherFactory.this.check(headers.raw(), this); + protected boolean doMatch(String line) { + return SPDXMatcherFactory.this.check(line, this); } - + @Override public void reset() { super.reset(); SPDXMatcherFactory.this.lastMatch = null; - } } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index 9a197702a..9d68e5b82 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -32,6 +32,7 @@ */ @ConfigComponent(type=Component.Type.Matcher, name="regex", desc="Performs a regex match using the enclosed the text") public class SimpleRegexMatcher extends AbstractSimpleMatcher { + @ConfigComponent(type=Component.Type.Text, desc="", parameterType=Pattern.class) private final Pattern pattern; /** @@ -58,7 +59,6 @@ public SimpleRegexMatcher(String id, Pattern pattern) { this.pattern = pattern; } - @ConfigComponent(type=Component.Type.Text, name="", desc="", parameterType=Pattern.class) private String getPattern() { return pattern.pattern(); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java index 91b00e410..77063c8b5 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java @@ -27,6 +27,7 @@ */ @ConfigComponent(type = Component.Type.Matcher, name = "text", desc = "Matches the enclosed the text") public class SimpleTextMatcher extends AbstractSimpleMatcher { + @ConfigComponent(type = Component.Type.Text, desc = "") private final String simpleText; /** @@ -54,7 +55,6 @@ public SimpleTextMatcher(String id, String simpleText) { this.simpleText = simpleText; } - @ConfigComponent(type = Component.Type.Text, name = "", desc = "") public String getSimpleText() { return this.simpleText; } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java index 2c6ac630f..c4c60b436 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java @@ -1,11 +1,14 @@ package org.apache.rat.config.parameters; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; - -@Retention(RetentionPolicy.RUNTIME) -public @interface ConfigChildren { - String name() default ""; - Class parameterType() default String.class; -} +import java.lang.annotation.Target; +// +//@Target(ElementType.FIELD) +//@Retention(RetentionPolicy.RUNTIME) +//public @interface ConfigChildren { +// String name() default ""; +// Class parameterType() default String.class; +//} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java index 0f1be1989..fe9658c31 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java @@ -1,15 +1,17 @@ package org.apache.rat.config.parameters; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +@Target({ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ConfigComponent { /** * The common name for the component. */ - String name(); + String name() default ""; /** * The description of the component. diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java index 4cde3a4e5..e90f0b0c2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java @@ -1,11 +1,13 @@ package org.apache.rat.config.parameters; +import java.lang.reflect.Method; import java.util.Collection; import java.util.Collections; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; +import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component.Type; public class Description { @@ -73,4 +75,27 @@ public Description(ConfigComponent configComponent, String value, Collection childrenOfType(Type type) { return children.values().stream().filter(d -> d.type == type).collect(Collectors.toList()); } + + private String methodName(String prefix) { + return prefix+name.substring(0,1).toUpperCase()+name.substring(1); + } + + public Method getter(Class clazz) throws NoSuchMethodException, SecurityException { + return clazz.getMethod(methodName("get")); + } + + public Method setter(Class clazz) throws NoSuchMethodException, SecurityException { + switch (type) { + case License: + throw new NoSuchMethodException("Can not set a License as a child"); + case Matcher: + return clazz.getMethod("add", IHeaderMatcher.Builder.class); + case Parameter: + return clazz.getMethod(methodName("set"), String.class); + case Text: + return clazz.getMethod("setText", String.class); + } + // should not happen + throw new IllegalStateException("Type "+type+" not valid."); + } } \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java index a8ef34e46..4808be506 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java @@ -1,5 +1,7 @@ package org.apache.rat.config.parameters; +import java.lang.annotation.Annotation; +import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; @@ -13,6 +15,7 @@ import java.util.Optional; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.AbstractHeaderMatcher; import org.apache.rat.license.ILicense; @@ -22,52 +25,13 @@ public class DescriptionBuilder { public static Description build(Object obj) { ConfigComponent configComponent = obj.getClass().getAnnotation(ConfigComponent.class); if (configComponent == null) { -// if (obj instanceof ILicense) { -// return build((ILicense) obj); -// } return null; } - Optional configChildren = getConfigChildren(obj.getClass()); - - List children = getConfigComponents(obj.getClass()).stream().map(m -> DescriptionBuilder.build(obj, m)) - .filter(Objects::nonNull).collect(Collectors.toList()); - if (configChildren.isPresent()) { - Method m = configChildren.get(); - try { - Object childrenObj = m.invoke(obj); - if (childrenObj instanceof Iterable) { - for (Object o : (Iterable) childrenObj) { - Description childDesc = DescriptionBuilder.build(o); - if (childDesc != null) { - children.add(childDesc); - } - } - } else { - Description childDesc = DescriptionBuilder.build(childrenObj); - if (childDesc != null) { - children.add(childDesc); - } - } - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); - } - } + List children = getConfigComponents(obj.getClass()); return new Description(configComponent, null, children); } - - private static Optional getConfigChildren(Class clazz) { - return Arrays.stream(clazz.getMethods()) - .filter(m -> Objects.nonNull(m.getAnnotation(ConfigChildren.class))).findFirst(); - } - - private static List getConfigComponents(Class clazz) { - return Arrays.stream(clazz.getMethods()) - .filter(m -> Objects.nonNull(m.getAnnotation(ConfigComponent.class))).collect(Collectors.toList()); - } - public static Description build(Object obj, Method m) { ConfigComponent configComponent = m.getAnnotation(ConfigComponent.class); @@ -85,6 +49,29 @@ public static Description build(Object obj, Method m) { } return new Description(configComponent, value, Collections.emptyList()); } + + + private static List getConfigComponents(Class clazz) { + if (clazz==null || clazz == String.class || clazz == Object.class) { + return Collections.emptyList(); + } + List result = new ArrayList<>(); + for (Field f : clazz.getDeclaredFields()) { + ConfigComponent configComponent = f.getAnnotation(ConfigComponent.class); + System.out.println(f.getName()); + if (configComponent != null) { + String name = StringUtils.isBlank(configComponent.name()) ? f.getName() : configComponent.name(); + Class childClazz = configComponent.parameterType() == null ? f.getType() : configComponent.parameterType(); + Description desc = new Description(configComponent.type(), name, + configComponent.desc(), null, getConfigComponents(childClazz)); + result.add(desc); + } + } + result.addAll(getConfigComponents(clazz.getSuperclass())); + Arrays.stream(clazz.getInterfaces()).forEach(c -> result.addAll(getConfigComponents(c))); + return result; + } + // public static Description build(ILicense license) { // IHeaderMatcher matcher = license.getMatcher(); @@ -107,13 +94,8 @@ public static Description buildMap(Class clazz) { if (configComponent == null) { return null; } - List children = new ArrayList<>(); - for (Method m : clazz.getMethods()) { - ConfigComponent config = m.getAnnotation(ConfigComponent.class); - if (config != null) { - children.add(new Description(config, null, null)); - } - } - return new Description(configComponent, null, children); + List children = getConfigComponents(clazz); + + return new Description(configComponent, null, children); } } 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 66f6b3531..fdd8b29c6 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 @@ -38,6 +38,7 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.FullTextMatcher; import org.apache.rat.analysis.matchers.SimpleTextMatcher; +import org.apache.rat.config.parameters.Description; import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.configuration.builders.AbstractBuilder; import org.apache.rat.configuration.builders.ChildContainerBuilder; @@ -224,36 +225,58 @@ public static IHeaderMatcher createTextMatcher(String id, String txt) { private AbstractBuilder parseMatcher(Node matcherNode) { AbstractBuilder builder = MatcherBuilderTracker.getMatcherBuilder(matcherNode.getNodeName()); - - NamedNodeMap nnm = matcherNode.getAttributes(); - for (int i = 0; i < nnm.getLength(); i++) { - Node n = nnm.item(i); - String methodName = "set" + StringUtils.capitalize(n.getNodeName()); - try { - MethodUtils.invokeExactMethod(builder, methodName, n.getNodeValue()); - } catch (NoSuchMethodException e) { - throw new ConfigurationException( - String.format("'%s' does not have a setter '%s' that takes a String argument", - matcherNode.getNodeName(), methodName)); - } catch (IllegalAccessException | InvocationTargetException | DOMException e) { - throw new ConfigurationException(e); - } - } - if (builder instanceof ChildContainerBuilder) { - ChildContainerBuilder ccb = (ChildContainerBuilder) builder; - nodeListConsumer(matcherNode.getChildNodes(), x -> { - if (x.getNodeType() == Node.ELEMENT_NODE) { - ccb.add(parseMatcher(x)); + try { + Class builtClass = builder.builtClass(); + Description description = DescriptionBuilder.buildMap(builtClass); + Map children = description.getChildren(); + Map attributes = attributes(matcherNode); + for (Map.Entry entry : attributes.entrySet()) { + Description d = children.get(entry.getKey()); + try { + d.setter(builder.getClass()).invoke(builder, entry.getValue()); + } catch (NoSuchMethodException e) { + throw new ConfigurationException( + String.format("'%s' does not have a '%s' setter that takes a String argument", + matcherNode.getNodeName(), entry.getKey())); } - }); - } - if (builder instanceof TextCaptureBuilder) { - ((TextCaptureBuilder) builder).setText(matcherNode.getTextContent().trim()); - } - - if (builder instanceof MatcherRefBuilder) { - ((MatcherRefBuilder) builder).setMatchers(matchers); + } + } catch (IllegalAccessException | InvocationTargetException | DOMException e) { + throw new ConfigurationException(e); + } catch (NoSuchMethodException e) { + throw new ConfigurationException( + String.format("'%s' does not have no argument build() method", + builder.getClass().getName())); } + +// NamedNodeMap nnm = matcherNode.getAttributes(); +// for (int i = 0; i < nnm.getLength(); i++) { +// Node n = nnm.item(i); +// String methodName = "set" + StringUtils.capitalize(n.getNodeName()); +// try { +// MethodUtils.invokeExactMethod(builder, methodName, n.getNodeValue()); +// } catch (NoSuchMethodException e) { +// throw new ConfigurationException( +// String.format("'%s' does not have a setter '%s' that takes a String argument", +// matcherNode.getNodeName(), methodName)); +// } catch (IllegalAccessException | InvocationTargetException | DOMException e) { +// throw new ConfigurationException(e); +// } +// } +// if (builder instanceof ChildContainerBuilder) { +// ChildContainerBuilder ccb = (ChildContainerBuilder) builder; +// nodeListConsumer(matcherNode.getChildNodes(), x -> { +// if (x.getNodeType() == Node.ELEMENT_NODE) { +// ccb.add(parseMatcher(x)); +// } +// }); +// } +// if (builder instanceof TextCaptureBuilder) { +// ((TextCaptureBuilder) builder).setText(matcherNode.getTextContent().trim()); +// } +// +// if (builder instanceof MatcherRefBuilder) { +// ((MatcherRefBuilder) builder).setMatchers(matchers); +// } if (builder.hasId()) { builder = new DelegatingBuilder(builder) { @@ -271,7 +294,6 @@ public IHeaderMatcher build() { private ILicense parseLicense(Node licenseNode) { Map attributes = attributes(licenseNode); ILicense.Builder builder = ILicense.builder(); - Description desc = DescriptionBuilder.build(null) builder.setLicenseFamilyCategory(attributes.get(FAMILY)); builder.setName(attributes.get(ATT_NAME)); diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java index d67264b42..33077521c 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java @@ -33,6 +33,8 @@ import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.IHeaderMatcher.Builder; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; /** * Constructs a builder that contains other builders. @@ -42,6 +44,7 @@ public abstract class ChildContainerBuilder extends AbstractBuilder { /** * The list of builders that will build the enclosed matchers. */ + @ConfigComponent(type=Component.Type.Matcher, desc="The enclosed Matchers", parameterType = IHeaderMatcher.Builder.class) protected final List children = new ArrayList<>(); /** diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java index a5268cb4f..5b0040017 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java @@ -18,26 +18,19 @@ */ package org.apache.rat.configuration.builders; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.Map; -import java.util.stream.Collectors; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaders; -import org.apache.rat.analysis.IHeaderMatcher.MatcherDescription; -import org.apache.rat.config.parameters.DescriptionImpl; -import org.apache.rat.config.parameters.Component.Description; -import org.apache.rat.license.ILicense; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; /** - * A reference matching Matcher builder. - *

- * This class stores a matcher id as a reference to the matcher. It also has a map of matcher ids to the matcher - * instances. When build is called the matcher reference is looked up in the map. If it is found then it is returned - * value from the {@code build()} call. If the reference is not located then a IHeaderMatcherProxy is returned. - * the IHeaderMatcherProxy is resolved in a later configuration construction phase. + * A reference matching Matcher builder.

This class stores a matcher id as a + * reference to the matcher. It also has a map of matcher ids to the matcher + * instances. When build is called the matcher reference is looked up in the + * map. If it is found then it is returned value from the {@code build()} call. + * If the reference is not located then a IHeaderMatcherProxy is returned. the + * IHeaderMatcherProxy is resolved in a later configuration construction phase. */ public class MatcherRefBuilder extends AbstractBuilder { private String referenceId; @@ -72,25 +65,32 @@ public IHeaderMatcher build() { @Override public String toString() { - return "MathcerRefBuilder: "+referenceId; + return "MathcerRefBuilder: " + referenceId; } - + /** - * A class that is a proxy to the actual matcher. It retrieves the actual matcher from the map of - * matcher ids to matcher instances one the first use of the matcher. This allows earlier read matchers - * to reference later constructed matchers as long as all the matchers are constructed before the earlier one is - * used. + * A class that is a proxy to the actual matcher. It retrieves the actual + * matcher from the map of matcher ids to matcher instances one the first use of + * the matcher. This allows earlier read matchers to reference later constructed + * matchers as long as all the matchers are constructed before the earlier one + * is used. */ - private class IHeaderMatcherProxy implements IHeaderMatcher { + @ConfigComponent(type = Component.Type.Matcher, name = "matcherRef", desc = "A pointer to another Matcher") + public static class IHeaderMatcherProxy implements IHeaderMatcher { + @ConfigComponent(type = Component.Type.Parameter, name = "refId", desc = "Reference to an existing matcher") private final String proxyId; private IHeaderMatcher wrapped; private Map matchers; - private IHeaderMatcherProxy(String proxyId, Map matchers) { + public IHeaderMatcherProxy(String proxyId, Map matchers) { this.proxyId = proxyId; this.matchers = matchers; } + public String getProxyId() { + return proxyId; + } + private void checkProxy() { if (wrapped == null) { wrapped = matchers.get(proxyId); @@ -114,21 +114,22 @@ public void reset() { } @Override - public boolean matches(IHeaders headers) { + public State matches(String line) { checkProxy(); - return wrapped.matches(headers); + return wrapped.matches(line); } @Override - public Description getDescription() { - - return new MatcherDescription(this, "MatcherProxy", "A proxy to another Matcher") { + public State currentState() { + checkProxy(); + return wrapped.currentState(); + } - @Override - public String getRefId() { - return proxyId; - } - }; + @Override + public State finalizeState() { + checkProxy(); + return wrapped.finalizeState(); } } + } diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java index b4909b075..84cdc6330 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java @@ -18,6 +18,7 @@ */ package org.apache.rat.license; +import java.lang.reflect.Method; import java.util.ArrayList; import java.util.Arrays; import java.util.Collection; @@ -28,9 +29,9 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.ConfigChildren; import org.apache.rat.config.parameters.ConfigComponent; import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; /** * The definition of a License. @@ -44,7 +45,6 @@ public interface ILicense extends IHeaderMatcher, Comparable, Componen /** * @return the notes associated with this license. May be null or empty. */ - @ConfigComponent(type=Component.Type.Parameter, name="notes", desc="Any notes related to this license.") String getNotes(); /** @@ -52,15 +52,12 @@ public interface ILicense extends IHeaderMatcher, Comparable, Componen * the family is returned. * @return the name of this license. */ - @ConfigComponent(type=Component.Type.Parameter, name="name", desc="The name of this license.") String getName(); - @ConfigComponent(type=Component.Type.Parameter, name="family", desc="The family this license belongs to.") default String getFamilyName() { return getLicenseFamily().getFamilyName(); } - @ConfigChildren IHeaderMatcher getMatcher(); /** 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 d6cc742c5..3ef11ed8e 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 @@ -22,8 +22,6 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaders; -import org.apache.rat.config.parameters.ConfigChildren; /** * A simple implementation of ILicense. @@ -62,7 +60,6 @@ public void setFamily(ILicenseFamily family) { } @Override - @ConfigChildren public IHeaderMatcher getMatcher() { return matcher; } @@ -82,8 +79,18 @@ public void reset() { } @Override - public boolean matches(IHeaders headers) { - return matcher.matches(headers); + public State matches(String line) { + return matcher.matches(line); + } + + @Override + public State finalizeState() { + return matcher.finalizeState(); + } + + @Override + public State currentState() { + return matcher.currentState(); } @Override diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java new file mode 100644 index 000000000..c456b1e3a --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java @@ -0,0 +1,40 @@ +package org.apache.rat.config.parameters; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNull; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import org.apache.rat.analysis.matchers.AndMatcher; +import org.apache.rat.analysis.matchers.CopyrightMatcher; +import org.junit.jupiter.api.Test; + +public class DescriptionBuilderTest { + + @Test + public void matcherMapBuildTest() { + + Description underTest = DescriptionBuilder.buildMap(CopyrightMatcher.class); + assertEquals(Component.Type.Matcher, underTest.getType()); + assertEquals("copyright", underTest.getCommonName()); + assertNotNull(underTest.getDescription()); + assertNull(underTest.getParamValue()); + assertEquals(4,underTest.getChildren().size()); + assertTrue(underTest.getChildren().containsKey("id")); + assertTrue(underTest.getChildren().containsKey("start")); + assertTrue(underTest.getChildren().containsKey("stop")); + assertTrue(underTest.getChildren().containsKey("owner")); + + underTest = DescriptionBuilder.buildMap(AndMatcher.class); + assertEquals(Component.Type.Matcher, underTest.getType()); + assertEquals("all", underTest.getCommonName()); + assertNotNull(underTest.getDescription()); + assertNull(underTest.getParamValue()); + assertEquals(2,underTest.getChildren().size()); + assertTrue(underTest.getChildren().containsKey("id")); + assertTrue(underTest.getChildren().containsKey("enclosed")); + Description desc = underTest.getChildren().get("enclosed"); + assertEquals(Component.Type.Matcher, underTest.getType()); + } + +} diff --git a/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java b/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java index a73103d95..5ab68f036 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java @@ -26,6 +26,7 @@ import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.configuration.builders.AbstractBuilder; import org.apache.rat.configuration.builders.AllBuilder; import org.apache.rat.configuration.builders.AnyBuilder; @@ -108,7 +109,7 @@ public void descriptionTest() throws NoSuchMethodException, SecurityException { reader.readMatcherBuilders(); IHeaderMatcher.Builder builder = MatcherBuilderTracker.getMatcherBuilder("copyright"); - Description desc = builder.getDescription(); + Description desc = DescriptionBuilder.buildMap(builder.builtClass()); print(desc); } diff --git a/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java index 4f2848f23..41a2cec99 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java @@ -18,7 +18,7 @@ public void descriptionTest() { SimpleLicense lic = new SimpleLicense( ILicenseFamily.builder().setLicenseFamilyCategory("familyId") .setLicenseFamilyName("TestingLicense: familyId").build(), - new TestingMatcher(), "derived from", "These are the notes", "My testing license", "TestingId"); + new TestingMatcher(), "These are the notes", "My testing license", "TestingId"); Description underTest = lic.getDescription(); assertEquals(Component.Type.License, underTest.getType()); assertEquals("My testing license", underTest.getCommonName()); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java index 76ccf2ff6..5a0ff785a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java @@ -36,7 +36,6 @@ public class ConfigurationReportTest { @Test public void testAll() throws RatException, IOException { ReportConfiguration reportConfiguration = new ReportConfiguration(DefaultLog.INSTANCE); - reportConfiguration.setFrom(Defaults.builder().build()); reportConfiguration.listFamilies(LicenseFilter.all); reportConfiguration.listLicenses(LicenseFilter.all); StringWriter sw = new StringWriter(); From 5a9dfce5ac7c4aad23a21c8b9a0fb507fad3f7e0 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Mon, 25 Mar 2024 08:43:17 +0100 Subject: [PATCH 28/77] started description test --- .../rat/config/parameters/Description.java | 22 +++++++ .../rat/analysis/matchers/AndMatcherTest.java | 58 +++++++++++++++++-- 2 files changed, 74 insertions(+), 6 deletions(-) diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java index e90f0b0c2..39ae7e1b8 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java @@ -1,6 +1,7 @@ package org.apache.rat.config.parameters; import java.lang.reflect.Method; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.Map; @@ -98,4 +99,25 @@ public Method setter(Class clazz) throws NoSuchMethodException, SecurityExcep // should not happen throw new IllegalStateException("Type "+type+" not valid."); } + + + @Override + public String toString() { + return toString(0); + } + + private String toString(int indent) { + char[] spaces = new char[indent]; + Arrays.fill(spaces, ' '); + String padding = String.copyValueOf(spaces); + String top = String.format( "%sDescription[ t:%s n:%s v:%s\n%s %s] ", padding, type, name, value, padding, desc); + if (children.isEmpty()) { + return top; + } + StringBuilder sb = new StringBuilder(top); + for (Description child : children.values()) { + sb.append("\n").append(child.toString(indent+2)); + } + return sb.toString(); + } } \ No newline at end of file diff --git a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java index 643665bab..68fefe750 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/analysis/matchers/AndMatcherTest.java @@ -23,20 +23,66 @@ import java.util.Arrays; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.IHeaders; +import org.apache.rat.analysis.IHeaderMatcher.State; +import org.apache.rat.config.parameters.Description; import org.apache.rat.testhelpers.TestingMatcher; import org.junit.jupiter.api.Test; -public class AndMatcherTest extends AbstractMatcherTest { + +public class AndMatcherTest { + + private void assertValues(IHeaderMatcher target, State hello, State world, State finalize) { + assertEquals(State.i, target.currentState()); + assertEquals(hello, target.matches("hello")); + assertEquals(hello, target.currentState()); + assertEquals(world, target.matches("world")); + assertEquals(world, target.currentState()); + assertEquals(finalize, target.finalizeState()); + assertEquals(finalize, target.currentState()); + } @Test public void trueTest() { + IHeaderMatcher one = new TestingMatcher("one", true); + IHeaderMatcher two = new TestingMatcher("two", false, true); + AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two)); + assertValues(target, State.i, State.t, State.t); + target.reset(); + assertEquals(State.i, one.currentState()); + assertEquals(State.i, two.currentState()); + assertEquals(State.i, target.currentState()); + } - IHeaderMatcher one = new TestingMatcher("one", true, true, false, false); - // only need 2 entries because when one is false two test does not get called. - IHeaderMatcher two = new TestingMatcher("two", true, false); + @Test + public void falseTest() { + IHeaderMatcher one = new TestingMatcher("one", true); + IHeaderMatcher two = new TestingMatcher("two", false, false); AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two)); - assertValues(target, true, false, false, false); + assertValues(target, State.i, State.i, State.f); target.reset(); + assertEquals(State.i, one.currentState()); + assertEquals(State.i, two.currentState()); + assertEquals(State.i, target.currentState()); + } + + @Test + public void indeterminentTest() { + IHeaderMatcher one = new TestingMatcher("one", false, false); + IHeaderMatcher two = new TestingMatcher("two", false, false); + AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two)); + assertValues(target, State.i, State.i, State.f); + target.reset(); + assertEquals(State.i, one.currentState()); + assertEquals(State.i, two.currentState()); + assertEquals(State.i, target.currentState()); + } + + @Test + public void descriptionTest() { + IHeaderMatcher one = new TestingMatcher("one", true); + IHeaderMatcher two = new TestingMatcher("two", false, true); + AndMatcher target = new AndMatcher("Testing", Arrays.asList(one, two)); + Description desc = target.getDescription(); + System.out.println( desc ); } } From a11254762d00b8688a0443b05995119adfd9d521 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Tue, 26 Mar 2024 17:45:38 +0100 Subject: [PATCH 29/77] toward parse/serialize licenses and matchers --- .../apache/rat/analysis/IHeaderMatcher.java | 12 +- .../rat/analysis/LicenseCollection.java | 7 +- .../matchers/AbstractMatcherContainer.java | 33 ++- .../rat/analysis/matchers/AndMatcher.java | 12 +- .../analysis/matchers/CopyrightMatcher.java | 11 +- .../analysis/matchers/FullTextMatcher.java | 5 - .../rat/analysis/matchers/NotMatcher.java | 11 +- .../rat/analysis/matchers/OrMatcher.java | 18 +- .../analysis/matchers/SPDXMatcherFactory.java | 10 +- .../analysis/matchers/SimpleRegexMatcher.java | 8 +- .../analysis/matchers/SimpleTextMatcher.java | 5 +- .../rat/config/parameters/Component.java | 37 ++- .../rat/config/parameters/ConfigChildren.java | 14 - .../config/parameters/ConfigComponent.java | 31 ++- .../rat/config/parameters/Description.java | 253 ++++++++++++++---- .../config/parameters/DescriptionBuilder.java | 124 +++++---- .../configuration/XMLConfigurationReader.java | 233 ++++++++-------- .../builders/AbstractBuilder.java | 11 +- .../configuration/builders/AllBuilder.java | 3 +- .../configuration/builders/AnyBuilder.java | 3 +- .../builders/ChildContainerBuilder.java | 42 +-- .../builders/CopyrightBuilder.java | 3 +- .../builders/MatcherRefBuilder.java | 12 +- .../configuration/builders/NotBuilder.java | 7 +- .../configuration/builders/RegexBuilder.java | 12 +- .../configuration/builders/SpdxBuilder.java | 7 +- .../configuration/builders/TextBuilder.java | 5 +- .../builders/TextCaptureBuilder.java | 26 -- .../java/org/apache/rat/license/ILicense.java | 12 +- .../org/apache/rat/license/SimpleLicense.java | 23 +- .../rat/report/ConfigurationReport.java | 149 ++++++++--- .../parameters/DescriptionBuilderTest.java | 4 +- .../ConfigurationReaderTest.java | 7 +- .../builders/TextBuilderTest.java | 92 +++++++ .../apache/rat/license/SimpleLicenseTest.java | 2 +- .../rat/report/ConfigurationReportTest.java | 7 + .../main/java/org/apache/rat/mp/License.java | 5 +- .../main/java/org/apache/rat/mp/Regex.java | 2 +- .../java/org/apache/rat/anttasks/License.java | 4 - .../java/org/apache/rat/anttasks/Regex.java | 9 +- .../src/test/java/org/example/Matcher.java | 10 +- 41 files changed, 810 insertions(+), 471 deletions(-) delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextCaptureBuilder.java create mode 100644 apache-rat-core/src/test/java/org/apache/rat/configuration/builders/TextBuilderTest.java diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java index c352a457d..b84684f53 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/IHeaderMatcher.java @@ -18,13 +18,7 @@ */ package org.apache.rat.analysis; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; - import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.ConfigComponent; import org.apache.rat.config.parameters.Description; import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.configuration.builders.AllBuilder; @@ -75,11 +69,15 @@ interface Builder { * @return a new IHeaderMatcher. */ IHeaderMatcher build(); - + default Class builtClass() throws NoSuchMethodException, SecurityException { return this.getClass().getMethod("build").getReturnType(); } + default Description getDescription() throws NoSuchMethodException, SecurityException { + return DescriptionBuilder.buildMap(builtClass()); + } + /** * @return an instance of the standard TextBuilder. * @see TextBuilder diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java index c81088c63..4b4f45338 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/LicenseCollection.java @@ -20,7 +20,6 @@ import java.util.Collection; import java.util.Collections; -import java.util.stream.Collectors; import org.apache.rat.analysis.matchers.AbstractMatcherContainer; import org.apache.rat.config.parameters.Description; @@ -49,7 +48,7 @@ class LicenseCollection extends AbstractMatcherContainer implements ILicense { * implementation from. May not be null. */ public LicenseCollection(Collection enclosed) { - super(enclosed); + super(enclosed, null); this.enclosed = Collections.unmodifiableCollection(enclosed); this.matchingLicense = null; } @@ -90,7 +89,7 @@ public ILicenseFamily getLicenseFamily() { public String getNotes() { return matchingLicense == null ? null : matchingLicense.getNotes(); } - + @Override public String getName() { return getLicenseFamily().getFamilyName(); @@ -102,7 +101,7 @@ public Description getDescription() { return matchingLicense.getDescription(); } return new Description(Type.License, "licenseCollection", - "A collection of ILicenses that acts as a single License for purposes of Analysis.", null, null); + "A collection of ILicenses that acts as a single License for purposes of Analysis.", false, null, null); } @Override diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java index 88e6e14cb..52ded6d93 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AbstractMatcherContainer.java @@ -20,8 +20,8 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.Objects; -import java.util.function.Consumer; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; @@ -33,40 +33,59 @@ */ public abstract class AbstractMatcherContainer extends AbstractHeaderMatcher { - @ConfigComponent(desc = "enclosed Matchers", type = Component.Type.Matcher) + @ConfigComponent(desc = "enclosed Matchers", type = Component.Type.Unlabled, parameterType = IHeaderMatcher.class) protected final Collection enclosed; + + @ConfigComponent(desc = "Resource to read matcher definitions from.", type = Component.Type.Parameter) + protected final String resource; public Collection getChildren() { return enclosed; } + /** * Constructs the abstract matcher container. If the {@code id} is not set then * a unique random identifier is created. The {@code enclosed} collection is * preserved in a new collection that retains the order of of the original * collection. - * + * * @param id The id for the matcher. * @param enclosed the collection of enclosed matchers. */ - public AbstractMatcherContainer(String id, Collection enclosed) { + public AbstractMatcherContainer(String id, Collection enclosed, String resource) { super(id); Objects.requireNonNull(enclosed, "The collection of IHeaderMatcher may not be null"); this.enclosed = new ArrayList<>(enclosed); + this.resource = resource; } /** * Constructs the abstract matcher container with a unique random id. The * {@code enclosed} collection is preserved in a new collection that retains the * order of of the original collection. - * + * * @param enclosed the collection of enclosed matchers. */ - public AbstractMatcherContainer(Collection enclosed) { - this(null, enclosed); + public AbstractMatcherContainer(Collection enclosed, String resource) { + this(null, enclosed, resource); } @Override public void reset() { enclosed.forEach(IHeaderMatcher::reset); } + + @Override + public State finalizeState() { + enclosed.forEach(IHeaderMatcher::finalizeState); + return currentState(); + } + + public Collection getEnclosed() { + return Collections.unmodifiableCollection(enclosed); + } + + public String getResource() { + return resource; + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java index bdd98203b..cf32ea944 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/AndMatcher.java @@ -24,13 +24,11 @@ import org.apache.rat.analysis.IHeaders; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; -import org.apache.rat.config.parameters.Description; -import org.apache.rat.config.parameters.DescriptionBuilder; /** * A matcher that performs a logical {@code AND} across all the contained matchers. */ -@ConfigComponent(type=Component.Type.Matcher, name="and", desc="Returns true if all enclosed matchers return true.") +@ConfigComponent(type = Component.Type.Matcher, name = "all", desc = "Returns true if all enclosed matchers return true.") public class AndMatcher extends AbstractMatcherContainer { /** @@ -38,16 +36,16 @@ public class AndMatcher extends AbstractMatcherContainer { * @param id the to use. If null or an empty string a unique random id will be created. * @param enclosed the enclosed collection. */ - public AndMatcher(String id, Collection enclosed) { - super(id, enclosed); + public AndMatcher(String id, Collection enclosed, String resource) { + super(id, enclosed, resource); } /** * Constructs the AndMatcher with the a unique random id and the enclosed collection. * @param enclosed the enclosed collection. */ - public AndMatcher(Collection enclosed) { - this(null, enclosed); + public AndMatcher(Collection enclosed, String resource) { + this(null, enclosed, resource); } @Override diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java index a30e8c7ff..d8660309b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/CopyrightMatcher.java @@ -22,11 +22,8 @@ import java.util.regex.Pattern; import org.apache.commons.lang3.StringUtils; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; -import org.apache.rat.config.parameters.Description; -import org.apache.rat.config.parameters.DescriptionBuilder; /** * Matches a typical Copyright header line only based on a regex pattern which @@ -42,7 +39,7 @@ * accepts "(C)", "(c)", and "©" in place of (or in addition to) the "Copyright" * or "copyright" keyword

*/ -@ConfigComponent(type=Component.Type.Matcher, name="copyright", desc="Matches copyright statements.") +@ConfigComponent(type = Component.Type.Matcher, name = "copyright", desc = "Matches copyright statements.") public class CopyrightMatcher extends AbstractSimpleMatcher { private static final String COPYRIGHT_SYMBOL_DEFN = "\\([Cc]\\)|©"; @@ -53,11 +50,11 @@ public class CopyrightMatcher extends AbstractSimpleMatcher { private final Pattern dateOwnerPattern; private final Pattern ownerDatePattern; - @ConfigComponent(type=Component.Type.Parameter, desc="The initial date of the copyright") + @ConfigComponent(type = Component.Type.Parameter, desc = "The initial date of the copyright") private final String start; - @ConfigComponent(type=Component.Type.Parameter, desc="The last date the copyright we modifed") + @ConfigComponent(type = Component.Type.Parameter, desc = "The last date the copyright we modifed") private final String stop; - @ConfigComponent(type=Component.Type.Parameter, name="owner", desc="The owner of the copyright") + @ConfigComponent(type = Component.Type.Parameter, name = "owner", desc = "The owner of the copyright") private final String owner; /** diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java index 2736606f4..f1a39427b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/FullTextMatcher.java @@ -88,9 +88,4 @@ public boolean matches(IHeaders headers) { } return false; } - - @Override - public Description getDescription() { - return new IHeaderMatcher.MatcherDescription(this, "text", "Matches text statement").addChildren(children); - } } \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java index ab4910531..9915e84ac 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/NotMatcher.java @@ -29,10 +29,10 @@ /** * An IHeaderMatcher that reverses the result of an enclosed matcher. */ -@ConfigComponent(type=Component.Type.Matcher, name="not", desc="Negates the enclosed matcher.") +@ConfigComponent(type = Component.Type.Matcher, name = "not", desc = "Negates the enclosed matcher.") public class NotMatcher extends AbstractHeaderMatcher { - @ConfigComponent(desc = "enclosed Matcher", type=Component.Type.Matcher) + @ConfigComponent(desc = "enclosed Matchers", type = Component.Type.Unlabled, parameterType = IHeaderMatcher.class) private final IHeaderMatcher enclosed; /** @@ -55,7 +55,6 @@ public NotMatcher(String id, IHeaderMatcher enclosed) { Objects.requireNonNull(enclosed, "enclosed matcher may not be null"); this.enclosed = enclosed; } - public List getEnclosed() { return Arrays.asList(enclosed); @@ -70,10 +69,4 @@ public boolean matches(IHeaders headers) { public void reset() { enclosed.reset(); } - - @Override - public Description getDescription() { - return new IHeaderMatcher.MatcherDescription(this, "not", "negates the enclosed matcher.") - .addChildMatchers(Arrays.asList(enclosed)); - } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java index 682d49422..1404d33dd 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/OrMatcher.java @@ -24,12 +24,11 @@ import org.apache.rat.analysis.IHeaders; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; -import org.apache.rat.config.parameters.Description; /** * A matcher that performs a logical {@code OR} across all the contained matchers. */ -@ConfigComponent(type=Component.Type.Matcher, name="or", desc="Returns true if at least one of the enclosed matchers return true.") +@ConfigComponent(type = Component.Type.Matcher, name = "any", desc = "Returns true if at least one of the enclosed matchers return true.") public class OrMatcher extends AbstractMatcherContainer { /** @@ -37,8 +36,8 @@ public class OrMatcher extends AbstractMatcherContainer { * * @param enclosed the enclosed matchers. */ - public OrMatcher(Collection enclosed) { - this(null, enclosed); + public OrMatcher(Collection enclosed, String resource) { + this(null, enclosed, resource); } /** @@ -47,8 +46,8 @@ public OrMatcher(Collection enclosed) { * @param id the id to use. * @param enclosed the enclosed matchers. */ - public OrMatcher(String id, Collection enclosed) { - super(id, enclosed); + public OrMatcher(String id, Collection enclosed, String resource) { + super(id, enclosed, resource); } @Override @@ -61,9 +60,4 @@ public boolean matches(IHeaders headers) { } return false; } - - @Override - public Description getDescription() { - return new IHeaderMatcher.MatcherDescription(this, "or", - "Returns true if one of the enclosed matchers return true.").addChildMatchers(enclosed); - }} +} diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java index bf57b4b08..eacd67989 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SPDXMatcherFactory.java @@ -26,10 +26,8 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.ConfigurationException; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; -import org.apache.rat.config.parameters.Description; /** * Defines a factory to produce matchers for an SPDX tag. SPDX tag is of the @@ -114,15 +112,15 @@ private boolean check(String line, Match caller) { return (lastMatch != null) && caller.spdxId.equals(lastMatch.spdxId); } - @ConfigComponent(type=Component.Type.Matcher, name="spdx", desc="Matches SPDX enclosed license identifier.") + @ConfigComponent(type = Component.Type.Matcher, name = "spdx", desc = "Matches SPDX enclosed license identifier.") public class Match extends AbstractSimpleMatcher { - @ConfigComponent(type=Component.Type.Text, name="spdx", desc="The spdx ID string") + @ConfigComponent(type = Component.Type.Parameter, name = "name", desc = "The spdx ID string") String spdxId; - public String getSpdx() { + public String getName() { return spdxId; } - + /** * Constructor. * diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java index 9d68e5b82..ebe0d6f48 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleRegexMatcher.java @@ -20,19 +20,17 @@ import java.util.regex.Pattern; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; -import org.apache.rat.config.parameters.Description; import org.apache.rat.analysis.IHeaders; /** * A simple regular expression matching IHeaderMatcher */ -@ConfigComponent(type=Component.Type.Matcher, name="regex", desc="Performs a regex match using the enclosed the text") +@ConfigComponent(type = Component.Type.Matcher, name = "regex", desc = "Performs a regex match using the enclosed the text") public class SimpleRegexMatcher extends AbstractSimpleMatcher { - @ConfigComponent(type=Component.Type.Text, desc="", parameterType=Pattern.class) + @ConfigComponent(type = Component.Type.Unlabled, desc = "", parameterType = Pattern.class) private final Pattern pattern; /** @@ -59,7 +57,7 @@ public SimpleRegexMatcher(String id, Pattern pattern) { this.pattern = pattern; } - private String getPattern() { + public String getPattern() { return pattern.pattern(); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java index 77063c8b5..0059c80f8 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java +++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/matchers/SimpleTextMatcher.java @@ -27,7 +27,7 @@ */ @ConfigComponent(type = Component.Type.Matcher, name = "text", desc = "Matches the enclosed the text") public class SimpleTextMatcher extends AbstractSimpleMatcher { - @ConfigComponent(type = Component.Type.Text, desc = "") + @ConfigComponent(type = Component.Type.Unlabled, name = "text", desc = "") private final String simpleText; /** @@ -55,7 +55,7 @@ public SimpleTextMatcher(String id, String simpleText) { this.simpleText = simpleText; } - public String getSimpleText() { + public String getText() { return this.simpleText; } @@ -63,5 +63,4 @@ public String getSimpleText() { public boolean doMatch(String line) { return line.contains(simpleText); } - } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java index f2dba8c9d..beedf3d08 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Component.java @@ -1,10 +1,43 @@ package org.apache.rat.config.parameters; +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +/** + * Interface that marks a configuration component like a License or Matcher. + * + */ public interface Component { - public enum Type { License, Matcher, Parameter, Text }; + public enum Type { + /** A License, the top level component. May not be used as a child of any component type. */ + License, + /** A Matcher */ + Matcher, + /** A Parameter for example the "id" parameter found in every component */ + Parameter, + /** A parameter without a name. Generally this is a value for the item. For example the enclosed matchers in the "or" license. */ + Unlabled, + /** A parameter that is supplied by the environment. Currently systems using builders have to handle seting this. For example the list of matchers for the "MatcherRefBuilder" */ + BuilderParam }; + /** - * Returns the component Description. + * Generates the component Description. * @return the component description. */ default Description getDescription() { diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java deleted file mode 100644 index c4c60b436..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigChildren.java +++ /dev/null @@ -1,14 +0,0 @@ -package org.apache.rat.config.parameters; - - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; -// -//@Target(ElementType.FIELD) -//@Retention(RetentionPolicy.RUNTIME) -//public @interface ConfigChildren { -// String name() default ""; -// Class parameterType() default String.class; -//} diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java index fe9658c31..0089052bf 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/ConfigComponent.java @@ -1,3 +1,21 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package org.apache.rat.config.parameters; import java.lang.annotation.ElementType; @@ -5,22 +23,29 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +/** + * An annotation that marks a configuration component. + * + */ @Target({ElementType.FIELD, ElementType.TYPE}) @Retention(RetentionPolicy.RUNTIME) public @interface ConfigComponent { /** - * The common name for the component. + * The common name for the component. If not specified the name of the field or class is used. */ String name() default ""; /** * The description of the component. */ - String desc(); + String desc() default ""; /** * The component type */ Component.Type type(); - Class parameterType() default String.class; + /** + * For collections defines the enclosed type. + */ + Class parameterType() default void.class; } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java index 39ae7e1b8..d8ceb50ca 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/Description.java @@ -1,73 +1,163 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ package org.apache.rat.config.parameters; +import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; import java.util.Arrays; import java.util.Collection; -import java.util.Collections; import java.util.Map; import java.util.TreeMap; import java.util.stream.Collectors; +import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component.Type; +import org.apache.rat.license.ILicense; +/** + * A description of a component. + */ public class Description { - - final Type type; - final String name; - final String desc; - final String value; - final Map children; - - public Description(Type type, String name, String desc, String value, Collection children) { + /** The type of component this describes */ + private final Type type; + /** The common name for the component. Set by ConfigComponent.name() or class/field name. */ + private final String name; + /** The description for the component */ + private final String desc; + /** The class of the getter/setter parameter */ + private final Class childClass; + /** True if the getter/setter expects a collection of childClass objects */ + private final boolean isCollection; + /** a map of name to Description for all the components that are children the described component */ + private final Map children; + + /** + * Constructor. + * @param type the type of the component. + * @param name the name of the component. + * @param desc the description of the component. + * @param isCollection true if the getter/setter expects a collection + * @param childClass the class for expected for the getter/setter. + * @param children the collection of descriptions for all the components that are children the described component. + */ + public Description(Type type, String name, String desc, boolean isCollection, Class childClass, + Collection children) { this.type = type; this.name = name; - this.desc = desc; - this.value = value; + this.desc = desc; + this.isCollection = isCollection; + this.childClass = childClass; this.children = new TreeMap<>(); if (children != null) { - children.forEach(d -> {this.children.put(d.name, d);}); + children.forEach(d -> { + this.children.put(d.name, d); + }); } } - - public Description(ConfigComponent configComponent, String value, Collection children) { - this(configComponent.type(), configComponent.name(), configComponent.desc(), value, children); + + /** + * Constructor + * @param configComponent the configuration component + * @param isCollection the collection flag. + * @param childClass the type of object that the method getter/setter expects. + * @param children the collection of descriptions for all the components that are children the described component. + */ + public Description(ConfigComponent configComponent, boolean isCollection, Class childClass, + Collection children) { + this(configComponent.type(), configComponent.name(), configComponent.desc(), isCollection, childClass, + children); } - + /** - * Gets the type of the object this description decribes. - * @return the obhect type. + * Gets the type of the component. + * @return the component type. */ - public Type getType() { return type; } - - /** - * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) - * May not be null. + public Type getType() { + return type; + } + + /** + * Get the isCollection flag. + * @return true if this is a collection. + */ + public boolean isCollection() { + return isCollection; + } + + /** + * Get the class of the objcts for the getter/setter. + * @return the getter/setter param class. + */ + public Class getChildType() { + return childClass; + } + + /** + * Gets the common name for the matcher. (e.g. 'text', 'spdx', etc.) May not be + * null. * @return The common name for the item being inspected. */ - public String getCommonName() { return name; } - + public String getCommonName() { + return name; + } + /** - * Gets the description of descriptive text for the component. - * May be an empty string or null. + * Gets the description of descriptive text for the component. May be an empty + * string or null. * @return the descriptive text; */ - public String getDescription() { return desc;} - + public String getDescription() { + return desc; + } + /** - * Gets the string parameter value. if this description has no value it should return null. + * Gets the string parameter value. if this description has no value it should + * return null. * @return the string value (default returns an empty string. */ - public String getParamValue() { return value; }; + public String getParamValue(Object o) { + if (isCollection) { + return null; + } + try { + Object val = getter(o.getClass()).invoke(o); + return val == null ? null : val.toString(); + } catch (IllegalArgumentException | IllegalAccessException | InvocationTargetException | NoSuchMethodException + | SecurityException e) { + System.err.format("Can not retrieve value for %s from %s\n", name, o.getClass()); + e.printStackTrace(); + return null; + } + } /** - * Gets a map of the parameters that the object contains. For example Copyright has 'start', 'stop', and 'owner' - * parameters. Some IHeaderMatchers have simple text values (e.g. 'regex' or 'text' types) these should list - * an unnamed parameter (empty string) with the text value. + * Gets a map of the parameters that the object contains. For example Copyright + * has 'start', 'stop', and 'owner' parameters. Some IHeaderMatchers have simple + * text values (e.g. 'regex' or 'text' types) these should list an unnamed + * parameter (empty string) with the text value. * @return the map of parameters to the objects that represent them. */ - public Map getChildren() { return children; }; - + public Map getChildren() { + return children; + } + /** * Get all the children of a specific type * @param type the type to return @@ -76,15 +166,39 @@ public Description(ConfigComponent configComponent, String value, Collection childrenOfType(Type type) { return children.values().stream().filter(d -> d.type == type).collect(Collectors.toList()); } - + private String methodName(String prefix) { - return prefix+name.substring(0,1).toUpperCase()+name.substring(1); + return prefix + name.substring(0, 1).toUpperCase() + name.substring(1); } - + + /** + * Returns the getter for the component in the specified class. + * @param clazz the Class to get the getter from. + * @return the getter Method. + * @throws NoSuchMethodException if the class does not have the getter. + * @throws SecurityException if the getter can not be accessed. + */ public Method getter(Class clazz) throws NoSuchMethodException, SecurityException { return clazz.getMethod(methodName("get")); } + + /** + * Returns the setter for the component in the specified class. + * Notes: + *
    + *
  • Licence can not be set in components. They are top level components.
  • + *
  • Matcher expects an "add" method that accepts an IHeaderMatcher.Builder.
  • + *
  • Parameter expects a {@code set(String)} method.
  • + *
  • Unlabled expects a {@code set(String)} method.
  • + *
  • BuilderParam expects a {@code set} method that takes a {@code childeClass} argument.
  • + *
+ * + * @param clazz the Class to get the getter from, generally a Builder class.. + * @return the getter Method. + * @throws NoSuchMethodException if the class does not have the getter. + * @throws SecurityException if the getter can not be accessed. + */ public Method setter(Class clazz) throws NoSuchMethodException, SecurityException { switch (type) { case License: @@ -92,31 +206,78 @@ public Method setter(Class clazz) throws NoSuchMethodException, SecurityExcep case Matcher: return clazz.getMethod("add", IHeaderMatcher.Builder.class); case Parameter: + case Unlabled: return clazz.getMethod(methodName("set"), String.class); - case Text: - return clazz.getMethod("setText", String.class); + case BuilderParam: + return clazz.getMethod(methodName("set"), childClass); } // should not happen - throw new IllegalStateException("Type "+type+" not valid."); + throw new IllegalStateException("Type " + type + " not valid."); + } + + /** + * Sets the children of values in the builder. + * Sets the parameters to the values specified in the map. Only children that accept + * string arguments should be specified. + * @param builder The Matcher builder to set the values in. + * @param attributes a Map of parameter names to values. + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + * @throws NoSuchMethodException + * @throws SecurityException + */ + public void setChildren(IHeaderMatcher.Builder builder, Map attributes) + throws IllegalAccessException, IllegalArgumentException, InvocationTargetException, NoSuchMethodException, + SecurityException { + for (Map.Entry entry : attributes.entrySet()) { + Description d = getChildren().get(entry.getKey()); + if (d == null) { + // TODO replace this with a logging message + System.err.println(String.format("%s does not define a Description. Missing ConfigComponent annotations.", entry.getKey())); + } else { + d.setter(builder.getClass()).invoke(builder, entry.getValue()); + } + } + } + + /** + * Sets the first Unlabled item that takes a string argument + * @param builder The Matcher builder to set the value in. + * @param value the value. + * @throws NoSuchMethodException + * @throws SecurityException + * @throws IllegalAccessException + * @throws IllegalArgumentException + * @throws InvocationTargetException + */ + public void setUnlabledText(IHeaderMatcher.Builder builder, String value) throws NoSuchMethodException, + SecurityException, IllegalAccessException, IllegalArgumentException, InvocationTargetException { + Collection unlabled = childrenOfType(Component.Type.Unlabled); + for (Description d : unlabled) { + if (!d.isCollection() && d.childClass == String.class) { + d.setter(builder.getClass()).invoke(builder, value); + } + } } - @Override public String toString() { return toString(0); } - + private String toString(int indent) { char[] spaces = new char[indent]; Arrays.fill(spaces, ' '); String padding = String.copyValueOf(spaces); - String top = String.format( "%sDescription[ t:%s n:%s v:%s\n%s %s] ", padding, type, name, value, padding, desc); + String top = String.format("%sDescription[ t:%s n:%s c:%s %s\n%s %s] ", padding, type, name, isCollection, + childClass, padding, desc); if (children.isEmpty()) { return top; } StringBuilder sb = new StringBuilder(top); for (Description child : children.values()) { - sb.append("\n").append(child.toString(indent+2)); + sb.append("\n").append(child.toString(indent + 2)); } return sb.toString(); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java index 4808be506..cbb676bdb 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/config/parameters/DescriptionBuilder.java @@ -1,69 +1,77 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + package org.apache.rat.config.parameters; -import java.lang.annotation.Annotation; import java.lang.reflect.Field; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; +import java.util.ArrayList; import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.ArrayList; -import java.util.Map; -import java.util.TreeMap; -import java.util.Objects; -import java.util.Optional; -import java.util.stream.Collectors; import org.apache.commons.lang3.StringUtils; -import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.matchers.AbstractHeaderMatcher; import org.apache.rat.license.ILicense; public class DescriptionBuilder { + /* do not instantiate */ + private DescriptionBuilder() {} + /** + * Create the description for the object. + * The object must have a ConfigComponent annotation or null will be returned. + * @param obj the object to process. + * @return the Description of the object. + */ public static Description build(Object obj) { - ConfigComponent configComponent = obj.getClass().getAnnotation(ConfigComponent.class); - if (configComponent == null) { - return null; - } - - List children = getConfigComponents(obj.getClass()); - - return new Description(configComponent, null, children); - } - - public static Description build(Object obj, Method m) { - ConfigComponent configComponent = m.getAnnotation(ConfigComponent.class); - if (configComponent == null) { - return null; - } - - String value = null; - try { - Object o = m.invoke(obj); - value = o == null ? null : o.toString(); - } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) { - // TODO Auto-generated catch block - e.printStackTrace(); + if (obj instanceof ILicense) { + ILicense license = (ILicense)obj; + Class clazz = obj.getClass(); + ConfigComponent configComponent = clazz.getAnnotation(ConfigComponent.class); + if (configComponent == null || configComponent.type() != Component.Type.License) { + throw new IllegalArgumentException(String.format("Licenses must have License type specified in ConfigComponent annotation. Annotation missing or incorrect in %s", clazz)); + } + List children = getConfigComponents(obj.getClass()); + return new Description(Component.Type.License, license.getId(), license.getName(), false, null, children); } - return new Description(configComponent, value, Collections.emptyList()); + return buildMap(obj.getClass()); } - + /** + * Build the list of descriptions for children of the class. + * @param clazz + * @return the Descriptions. of the child elements. + */ private static List getConfigComponents(Class clazz) { - if (clazz==null || clazz == String.class || clazz == Object.class) { + if (clazz == null || clazz == String.class || clazz == Object.class) { return Collections.emptyList(); } List result = new ArrayList<>(); - for (Field f : clazz.getDeclaredFields()) { - ConfigComponent configComponent = f.getAnnotation(ConfigComponent.class); - System.out.println(f.getName()); + for (Field field : clazz.getDeclaredFields()) { + ConfigComponent configComponent = field.getAnnotation(ConfigComponent.class); if (configComponent != null) { - String name = StringUtils.isBlank(configComponent.name()) ? f.getName() : configComponent.name(); - Class childClazz = configComponent.parameterType() == null ? f.getType() : configComponent.parameterType(); - Description desc = new Description(configComponent.type(), name, - configComponent.desc(), null, getConfigComponents(childClazz)); + String name = StringUtils.isBlank(configComponent.name()) ? field.getName() : configComponent.name(); + Class childClazz = configComponent.parameterType() == void.class ? field.getType() + : configComponent.parameterType(); + boolean isCollection = Iterable.class.isAssignableFrom(field.getType()); + + Description desc = new Description(configComponent.type(), name, configComponent.desc(), isCollection, + childClazz, getConfigComponents(childClazz)); result.add(desc); } } @@ -72,30 +80,18 @@ private static List getConfigComponents(Class clazz) { return result; } - -// public static Description build(ILicense license) { -// IHeaderMatcher matcher = license.getMatcher(); -// List children = new ArrayList<>(); -// for (Method m : license.getClass().getMethods()) { -// ConfigComponent config = m.getAnnotation(ConfigComponent.class); -// if (config != null) { -// Object value = m.invoke(license); -// children.add( new Description(config, value == null ? null : value.toString(), null)); -// } -// } -// if (matcher != null) { -// children.add(DescriptionBuilder.build(matcher)); -// } -// return new Description(Component.Type.License, license.getName(), "", null, children); -// } - + /** + * Create a description for a class. + * @param clazz the class to build the description for. + * @return the Description of the class or null if no ConfigComponent annotation was found on the class. + */ public static Description buildMap(Class clazz) { ConfigComponent configComponent = clazz.getAnnotation(ConfigComponent.class); if (configComponent == null) { return null; } List children = getConfigComponents(clazz); - - return new Description(configComponent, null, children); + + return new Description(configComponent, false, null, children); } } 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 fdd8b29c6..62595a5ac 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 @@ -23,27 +23,25 @@ import java.net.URL; import java.util.Collections; import java.util.HashMap; +import java.util.Iterator; import java.util.Map; +import java.util.Optional; import java.util.SortedSet; import java.util.TreeSet; import java.util.function.Consumer; +import java.util.function.Predicate; import javax.xml.parsers.DocumentBuilder; import javax.xml.parsers.DocumentBuilderFactory; import javax.xml.parsers.ParserConfigurationException; -import org.apache.commons.beanutils.MethodUtils; import org.apache.commons.lang3.StringUtils; import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.analysis.matchers.FullTextMatcher; -import org.apache.rat.analysis.matchers.SimpleTextMatcher; +import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.Description; import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.configuration.builders.AbstractBuilder; -import org.apache.rat.configuration.builders.ChildContainerBuilder; -import org.apache.rat.configuration.builders.MatcherRefBuilder; -import org.apache.rat.configuration.builders.TextCaptureBuilder; import org.apache.rat.license.ILicense; import org.apache.rat.license.ILicenseFamily; import org.apache.rat.license.LicenseFamilySetFactory; @@ -57,30 +55,20 @@ import org.xml.sax.SAXException; /** - * A class that reads the XML configuration file format. - *

- * {@code }
- * {@code }
- * {@code }
- * {@code }
+ * A class that reads the XML configuration file format.

+ * {@code }
{@code }
+ * {@code }
{@code }
* {@code }
* {@code }
- * {@code }
- * {@code ...}
+ * {@code }
{@code ...}
* {@code ... }
* {@code }
- * {@code }
- * {@code
}
- * {@code
}
- * {@code }
- * {@code }
- * {@code
}
- * {@code }
- * {@code }
- * {@code }
- * {@code
}
- * {@code
}
- *

+ * {@code }
{@code }
+ * {@code }
{@code }
+ * {@code }
{@code
}
+ * {@code }
{@code }
+ * {@code }
{@code
}
+ * {@code }

*/ public class XMLConfigurationReader implements LicenseReader, MatcherReader { @@ -112,6 +100,11 @@ public class XMLConfigurationReader implements LicenseReader, MatcherReader { private final SortedSet licenseFamilies; private final SortedSet approvedFamilies; + private final Predicate> MATCHER_FILTER = (e) -> { + Description d = e.getValue(); + return d.getType() == Component.Type.Unlabled && IHeaderMatcher.class.isAssignableFrom(d.getChildType()); + }; + /** * Constructs the XML configuration reader. */ @@ -144,7 +137,7 @@ public void addLicenses(URL url) { /** * Read the urls and extract the DOM information to create new objects. - * + * * @param urls The URLs to read. */ public void read(URL... urls) { @@ -165,7 +158,7 @@ public void read(URL... urls) { /** * Applies the {@code consumer} to each node in the {@code list} - * + * * @param list the NodeList to process * @param consumer the consumer to apply to each node in the list. */ @@ -177,17 +170,15 @@ private void nodeListConsumer(NodeList list, Consumer consumer) { /** * Merge the new document into the document that this reader processes. - * + * * @param newDoc the Document to merge. */ public void add(Document newDoc) { - nodeListConsumer(newDoc.getElementsByTagName(FAMILIES), - nl -> nodeListConsumer( nl.getChildNodes(), + nodeListConsumer(newDoc.getElementsByTagName(FAMILIES), nl -> nodeListConsumer(nl.getChildNodes(), n -> familiesElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true))))); nodeListConsumer(newDoc.getElementsByTagName(LICENSE), n -> licensesElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true)))); - nodeListConsumer(newDoc.getElementsByTagName(APPROVED), - nl -> nodeListConsumer( nl.getChildNodes(), + nodeListConsumer(newDoc.getElementsByTagName(APPROVED), nl -> nodeListConsumer(nl.getChildNodes(), n -> approvedElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true))))); nodeListConsumer(newDoc.getElementsByTagName(MATCHERS), n -> matchersElement.appendChild(rootElement.getOwnerDocument().adoptNode(n.cloneNode(true)))); @@ -195,7 +186,7 @@ public void add(Document newDoc) { /** * Get a map of Node attribute names to values. - * + * * @param node The node to process * @return the map of attributes on the node */ @@ -209,86 +200,117 @@ private Map attributes(Node node) { return result; } - /** - * Create a text matcher. Will construct a FullTextMatcher or a - * SimpleTextMatcher depending on the complexity of the text. - * - * @param id the id for the Matcher. - * @param txt the text to match - * @return the IHeaderMatcher that matches the text. - */ - public static IHeaderMatcher createTextMatcher(String id, String txt) { - boolean complex = txt.contains(" ") | txt.contains("\\t") | txt.contains("\\n") | txt.contains("\\r") - | txt.contains("\\f") | txt.contains("\\v"); - return complex ? new FullTextMatcher(id, txt) : new SimpleTextMatcher(id, txt); + private void callSetter(Description desc, IHeaderMatcher.Builder builder, Object value) { + try { + desc.setter(builder.getClass()).invoke(builder, value); + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException + | SecurityException e) { + throw new ConfigurationException(e.getMessage(), e); + } } private AbstractBuilder parseMatcher(Node matcherNode) { - AbstractBuilder builder = MatcherBuilderTracker.getMatcherBuilder(matcherNode.getNodeName()); + final AbstractBuilder builder = MatcherBuilderTracker.getMatcherBuilder(matcherNode.getNodeName()); + if (builder == null) { + throw new ConfigurationException(String.format("No builder found for: %s", matcherNode.getNodeName())); + } try { - Class builtClass = builder.builtClass(); - Description description = DescriptionBuilder.buildMap(builtClass); - Map children = description.getChildren(); - Map attributes = attributes(matcherNode); - for (Map.Entry entry : attributes.entrySet()) { - Description d = children.get(entry.getKey()); - try { - d.setter(builder.getClass()).invoke(builder, entry.getValue()); - } catch (NoSuchMethodException e) { - throw new ConfigurationException( - String.format("'%s' does not have a '%s' setter that takes a String argument", - matcherNode.getNodeName(), entry.getKey())); + final Description description = DescriptionBuilder.buildMap(builder.builtClass()); + + for (Description desc : description.childrenOfType(Component.Type.BuilderParam)) { + if ("matchers".equals(desc.getCommonName())) { + callSetter(desc, builder, matchers); + } else { + throw new ConfigurationException(String.format("Unknown BuilderParam: %s", desc.getCommonName())); + } + } + + // process the attributes + description.setChildren(builder, attributes(matcherNode)); + description.setUnlabledText(builder, matcherNode.getTextContent()); + + // check child nodes. + if (matcherNode.hasChildNodes()) { + Map children = new HashMap<>(); + nodeListConsumer(matcherNode.getChildNodes(), (n) -> { + if (n.getNodeType() == Node.ELEMENT_NODE) { + children.put(n.getNodeName(), n); + } + }); + Iterator> iter = children.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry entry = iter.next(); + Description childDescription = description.getChildren().get(entry.getKey()); + if (childDescription != null) { + switch (childDescription.getType()) { + case License: + case Matcher: + case BuilderParam: + throw new ConfigurationException( + String.format("%s may not be used as an enclosed matcher. %s '%s' found in '%s'", + childDescription.getType(), childDescription.getType(), + childDescription.getCommonName(), description.getCommonName())); + case Parameter: + callSetter(childDescription, builder, entry.getValue().getTextContent()); + iter.remove(); + break; + case Unlabled: + try { + childDescription.setUnlabledText(builder, entry.getValue().getTextContent()); + iter.remove(); + } catch (NoSuchMethodException | SecurityException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException | DOMException e) { + throw new ConfigurationException( + String.format("Can not set parameter: %s", childDescription.getCommonName()), + e); + } + break; + } + } + } + + // now handle all the embedded matchers. + if (!children.isEmpty()) { + Optional> opt = description.getChildren().entrySet().stream() + .filter(MATCHER_FILTER).findAny(); + if (opt.isPresent()) { + iter = children.entrySet().iterator(); + while (iter.hasNext()) { + Map.Entry child = iter.next(); + if (MatcherBuilderTracker.getMatcherBuilder(child.getKey()) != null) { + AbstractBuilder b = parseMatcher(child.getValue()); + callSetter(b.getDescription(), builder, b); + iter.remove(); + } + + } + } + + } + if (!children.isEmpty()) { + children.keySet().forEach(s -> System.out.format("unrecognised child node '%s' in node '%s'\n", s, + matcherNode.getNodeName())); } } } catch (IllegalAccessException | InvocationTargetException | DOMException e) { throw new ConfigurationException(e); } catch (NoSuchMethodException e) { throw new ConfigurationException( - String.format("'%s' does not have no argument build() method", - builder.getClass().getName())); + String.format("'%s' does not have no argument build() method", builder.getClass().getName())); } - -// NamedNodeMap nnm = matcherNode.getAttributes(); -// for (int i = 0; i < nnm.getLength(); i++) { -// Node n = nnm.item(i); -// String methodName = "set" + StringUtils.capitalize(n.getNodeName()); -// try { -// MethodUtils.invokeExactMethod(builder, methodName, n.getNodeValue()); -// } catch (NoSuchMethodException e) { -// throw new ConfigurationException( -// String.format("'%s' does not have a setter '%s' that takes a String argument", -// matcherNode.getNodeName(), methodName)); -// } catch (IllegalAccessException | InvocationTargetException | DOMException e) { -// throw new ConfigurationException(e); -// } -// } -// if (builder instanceof ChildContainerBuilder) { -// ChildContainerBuilder ccb = (ChildContainerBuilder) builder; -// nodeListConsumer(matcherNode.getChildNodes(), x -> { -// if (x.getNodeType() == Node.ELEMENT_NODE) { -// ccb.add(parseMatcher(x)); -// } -// }); -// } -// if (builder instanceof TextCaptureBuilder) { -// ((TextCaptureBuilder) builder).setText(matcherNode.getTextContent().trim()); -// } -// -// if (builder instanceof MatcherRefBuilder) { -// ((MatcherRefBuilder) builder).setMatchers(matchers); -// } - - if (builder.hasId()) { - builder = new DelegatingBuilder(builder) { - @Override - public IHeaderMatcher build() { - IHeaderMatcher result = delegate.build(); - matchers.put(result.getId(), result); - return result; - } - }; - } - return builder; + return builder.hasId() ? new DelegatingBuilder(builder) { + @Override + public IHeaderMatcher build() { + IHeaderMatcher result = delegate.build(); + matchers.put(result.getId(), result); + return result; + } + + @Override + public Description getDescription() throws NoSuchMethodException, SecurityException { + return delegate.getDescription(); + } + } : builder; } private ILicense parseLicense(Node licenseNode) { @@ -302,7 +324,7 @@ private ILicense parseLicense(Node licenseNode) { StringBuilder notesBuilder = new StringBuilder(); nodeListConsumer(licenseNode.getChildNodes(), x -> { if (x.getNodeType() == Node.ELEMENT_NODE) { - if (x.getNodeName().equals(NOTE)) { + if (NOTE.equals(x.getNodeName())) { notesBuilder.append(x.getTextContent()).append("\n"); } else { builder.setMatcher(parseMatcher(x)); @@ -323,7 +345,6 @@ public SortedSet readLicenses() { } return Collections.unmodifiableSortedSet(licenses); } - @Override public SortedSet readFamilies() { @@ -335,7 +356,7 @@ public SortedSet readFamilies() { } return Collections.unmodifiableSortedSet(licenseFamilies); } - + private ILicenseFamily parseFamily(Map attributes) { if (attributes.containsKey(ATT_ID)) { ILicenseFamily.Builder builder = ILicenseFamily.builder(); diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java index 6d105fb50..3da1cb0e6 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AbstractBuilder.java @@ -18,13 +18,8 @@ */ package org.apache.rat.configuration.builders; -import java.lang.reflect.Method; - import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; -import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.Description; -import org.apache.rat.config.parameters.DescriptionBuilder; /** * An abstract IHeaderMatcher.Builder. @@ -55,16 +50,16 @@ public final AbstractBuilder setId(String id) { public final boolean hasId() { return !StringUtils.isBlank(id); } - + /** * @return the id as specified in the builder. */ protected String getId() { return id; } - + @Override public String toString() { - return String.format( "%s with id %s", this.getClass(), id); + return String.format("%s with id %s", this.getClass(), id); } } \ No newline at end of file diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java index debeda69c..c682822ea 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AllBuilder.java @@ -18,7 +18,6 @@ */ package org.apache.rat.configuration.builders; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.AndMatcher; /** @@ -28,6 +27,6 @@ public class AllBuilder extends ChildContainerBuilder { @Override public AndMatcher build() { - return new AndMatcher(getId(), getChildren()); + return new AndMatcher(getId(), getChildren(), resource); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java index 6ae1952f4..73d1b85f2 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/AnyBuilder.java @@ -18,7 +18,6 @@ */ package org.apache.rat.configuration.builders; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.OrMatcher; /** @@ -28,6 +27,6 @@ public class AnyBuilder extends ChildContainerBuilder { @Override public OrMatcher build() { - return new OrMatcher(getId(), getChildren()); + return new OrMatcher(getId(), getChildren(), resource); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java index 33077521c..6180c8e22 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/ChildContainerBuilder.java @@ -33,8 +33,6 @@ import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.IHeaderMatcher.Builder; -import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.ConfigComponent; /** * Constructs a builder that contains other builders. @@ -44,8 +42,9 @@ public abstract class ChildContainerBuilder extends AbstractBuilder { /** * The list of builders that will build the enclosed matchers. */ - @ConfigComponent(type=Component.Type.Matcher, desc="The enclosed Matchers", parameterType = IHeaderMatcher.Builder.class) protected final List children = new ArrayList<>(); + + protected String resource; /** * Empty default constructor. @@ -55,27 +54,28 @@ protected ChildContainerBuilder() { /** * Reads a text file. Each line becomes a text matcher in the resulting list. - * + * * @param resourceName the name of the resource to read. * @return a List of Matchers, one for each non-empty line in the input file. */ public AbstractBuilder setResource(String resourceName) { - URL url = this.getClass().getResource(resourceName); - try (final InputStream in = url.openStream()) { - BufferedReader buffer = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); - String txt; - while (null != (txt = buffer.readLine())) { - txt = txt.trim(); - if (StringUtils.isNotBlank(txt)) { - children.add(Builder.text().setText(txt)); - } + URL url = this.getClass().getResource(resourceName); + try (final InputStream in = url.openStream()) { + BufferedReader buffer = new BufferedReader(new InputStreamReader(in, StandardCharsets.UTF_8)); + String txt; + while (null != (txt = buffer.readLine())) { + txt = txt.trim(); + if (StringUtils.isNotBlank(txt)) { + children.add(Builder.text().setText(txt)); } - return this; - } catch (IOException e) { - throw new ConfigurationException("Unable to read matching text file: " + resourceName, e); } + this.resource = resourceName; + return this; + } catch (IOException e) { + throw new ConfigurationException("Unable to read matching text file: " + resourceName, e); + } } - + /** * Adds a builder to the list of builders. * @param child the child builder to add. @@ -85,7 +85,7 @@ public AbstractBuilder add(IHeaderMatcher.Builder child) { children.add(child); return this; } - + /** * Adds a collection of builders to the list of child builders. * @param children the children to add. @@ -102,11 +102,11 @@ public AbstractBuilder add(Collection children) { public List getChildren() { return children.stream().map(IHeaderMatcher.Builder::build).collect(Collectors.toList()); } - + @Override public String toString() { - StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()).append( ":"); - children.stream().map(Object::toString).forEach( x -> sb.append("\n").append(x)); + StringBuilder sb = new StringBuilder(this.getClass().getSimpleName()).append(":"); + children.stream().map(Object::toString).forEach(x -> sb.append("\n").append(x)); return sb.toString(); } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java index 73c6e70c4..e74b270f3 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/CopyrightBuilder.java @@ -18,7 +18,6 @@ */ package org.apache.rat.configuration.builders; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.CopyrightMatcher; /** @@ -63,7 +62,7 @@ public CopyrightBuilder setOwner(String owner) { public CopyrightMatcher build() { return new CopyrightMatcher(getId(), start, end, owner); } - + @Override public String toString() { return String.format("Copyright Builder: s:%s e:%s o:%s", start, end, owner); diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java index 5b0040017..b2b07a62b 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/MatcherRefBuilder.java @@ -20,6 +20,7 @@ import java.util.Map; +import org.apache.rat.ConfigurationException; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.ConfigComponent; @@ -47,6 +48,11 @@ public MatcherRefBuilder setRefId(String refId) { return this; } + @Override + public Class builtClass() throws NoSuchMethodException, SecurityException { + return IHeaderMatcherProxy.class; + } + /** * Set the Map of matcher ids to matcher instances. * @param matchers the Map of ids to instances. @@ -59,6 +65,9 @@ public MatcherRefBuilder setMatchers(Map matchers) { @Override public IHeaderMatcher build() { + if (matchers == null) { + throw new ConfigurationException("'matchers' not set"); + } IHeaderMatcher result = matchers.get(referenceId); return result != null ? result : new IHeaderMatcherProxy(referenceId, matchers); } @@ -80,6 +89,7 @@ public static class IHeaderMatcherProxy implements IHeaderMatcher { @ConfigComponent(type = Component.Type.Parameter, name = "refId", desc = "Reference to an existing matcher") private final String proxyId; private IHeaderMatcher wrapped; + @ConfigComponent(type = Component.Type.BuilderParam, desc = "Map of matcher names to matcher instances") private Map matchers; public IHeaderMatcherProxy(String proxyId, Map matchers) { @@ -87,7 +97,7 @@ public IHeaderMatcherProxy(String proxyId, Map matchers) this.matchers = matchers; } - public String getProxyId() { + public String getRefId() { return proxyId; } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java index a3967f490..c70abd996 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/NotBuilder.java @@ -19,14 +19,13 @@ package org.apache.rat.configuration.builders; import org.apache.rat.ConfigurationException; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.NotMatcher; /** * A builder for the NotMatcher. */ public class NotBuilder extends ChildContainerBuilder { - + @Override public NotMatcher build() { if (children.size() != 1) { @@ -34,9 +33,9 @@ public NotMatcher build() { } return new NotMatcher(getId(), children.get(0).build()); } - + @Override public String toString() { - return String.format( "NotBuilder: %s", !children.isEmpty() ? children.get(0) : null ); + return String.format("NotBuilder: %s", !children.isEmpty() ? children.get(0) : null); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java index db90ea1e2..e43b3bade 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/RegexBuilder.java @@ -21,7 +21,6 @@ import java.util.regex.Pattern; import org.apache.rat.ConfigurationException; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.SimpleRegexMatcher; /** @@ -32,14 +31,13 @@ public class RegexBuilder extends AbstractBuilder { private Pattern pattern; /** - * Sets the regex expression. - * This method compiles the string into a pattern and may throw any exception thrown by the - * {@code Pattern.compile(String)} method. + * Sets the regex expression. This method compiles the string into a pattern and + * may throw any exception thrown by the {@code Pattern.compile(String)} method. * @param exp the expression as a string. * @return this builder for chaining. * @see Pattern#compile(String) */ - public RegexBuilder setExpr(String exp) { + public RegexBuilder setPattern(String exp) { this.pattern = exp == null ? null : Pattern.compile(exp); return this; } @@ -51,10 +49,10 @@ public SimpleRegexMatcher build() { } return new SimpleRegexMatcher(pattern); } - + @Override public String toString() { - return String.format("RegexBuilder: %s", pattern==null? null: pattern.pattern()); + return String.format("RegexBuilder: %s", pattern == null ? null : pattern.pattern()); } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java index fd572bcc8..a57e0a09a 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/SpdxBuilder.java @@ -20,7 +20,6 @@ import java.util.Objects; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.SPDXMatcherFactory; /** @@ -36,7 +35,7 @@ public class SpdxBuilder extends AbstractBuilder { * @return this builder for chaining. */ public SpdxBuilder setName(String name) { - Objects.requireNonNull(name, "name must not be null"); + Objects.requireNonNull(name, "spdx name must not be null"); this.name = name; return this; } @@ -45,9 +44,9 @@ public SpdxBuilder setName(String name) { public SPDXMatcherFactory.Match build() { return SPDXMatcherFactory.INSTANCE.create(name); } - + @Override public String toString() { - return "SpdxBuilder: "+name; + return "SpdxBuilder: " + name; } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java index 45d00531f..4a38b8a36 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java +++ b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextBuilder.java @@ -22,19 +22,16 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.ConfigurationException; -import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.analysis.matchers.FullTextMatcher; import org.apache.rat.analysis.matchers.SimpleTextMatcher; /** * Builds text based matcher based on the complexity of the text to match. */ -public class TextBuilder extends AbstractBuilder implements TextCaptureBuilder { +public class TextBuilder extends AbstractBuilder { private String text; - @SuppressWarnings("unchecked") - @Override public TextBuilder setText(String text) { Objects.requireNonNull(text, "text may not be null"); this.text = text; diff --git a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextCaptureBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextCaptureBuilder.java deleted file mode 100644 index 8ad765974..000000000 --- a/apache-rat-core/src/main/java/org/apache/rat/configuration/builders/TextCaptureBuilder.java +++ /dev/null @@ -1,26 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one - * or more contributor license agreements. See the NOTICE file - * distributed with this work for additional information - * regarding copyright ownership. The ASF licenses this file - * to you under the Apache License, Version 2.0 (the - * "License"); you may not use this file except in compliance - * with the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, - * software distributed under the License is distributed on an - * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY - * KIND, either express or implied. See the License for the - * specific language governing permissions and limitations - * under the License. - */ -package org.apache.rat.configuration.builders; - -/** - * A marker interface for builders that accept text plain text to match. - */ -public interface TextCaptureBuilder { - T setText(String text); -} diff --git a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java index 84cdc6330..a3c1e3b0c 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java +++ b/apache-rat-core/src/main/java/org/apache/rat/license/ILicense.java @@ -18,25 +18,19 @@ */ package org.apache.rat.license; -import java.lang.reflect.Method; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collection; import java.util.Comparator; -import java.util.List; import java.util.Objects; import java.util.SortedSet; import org.apache.rat.analysis.IHeaderMatcher; import org.apache.rat.config.parameters.Component; -import org.apache.rat.config.parameters.ConfigComponent; import org.apache.rat.config.parameters.Description; import org.apache.rat.config.parameters.DescriptionBuilder; /** * The definition of a License. */ -public interface ILicense extends IHeaderMatcher, Comparable, Component { +public interface ILicense extends IHeaderMatcher, Comparable { /** * @return the ILicenseFamily implementation for this license. */ @@ -53,11 +47,11 @@ public interface ILicense extends IHeaderMatcher, Comparable, Componen * @return the name of this license. */ String getName(); - + default String getFamilyName() { return getLicenseFamily().getFamilyName(); } - + IHeaderMatcher getMatcher(); /** 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 3ef11ed8e..67aef9c9d 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 @@ -18,21 +18,34 @@ */ package org.apache.rat.license; +import java.util.Collection; import java.util.Objects; import org.apache.commons.lang3.StringUtils; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; +import org.apache.rat.config.parameters.Component.Type; +import org.apache.rat.config.parameters.ConfigComponent; /** * A simple implementation of ILicense. */ -class SimpleLicense implements ILicense { +@ConfigComponent(type=Component.Type.License) +public class SimpleLicense implements ILicense { + + @ConfigComponent(type=Component.Type.BuilderParam, desc = "The family this license belongs to.", parameterType = ILicenseFamily.class) private ILicenseFamily family; + + @ConfigComponent(type=Component.Type.Unlabled, desc = "The matcher for this license.") private IHeaderMatcher matcher; - + @ConfigComponent(type=Component.Type.Parameter, desc = "The notes about this license.") private String notes; + @ConfigComponent(type=Component.Type.Parameter, desc = "The name of this license.") private String name; + @ConfigComponent(type=Component.Type.Parameter, desc = "The ID for this license.") private String id; SimpleLicense(ILicenseFamily family, IHeaderMatcher matcher, String notes, String name, @@ -112,4 +125,10 @@ public String getNotes() { public String getName() { return name; } + + @Override + public Description getDescription() { + return DescriptionBuilder.build(this); + + } } diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java index 9b02fd9d5..df4fdb972 100644 --- a/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java +++ b/apache-rat-core/src/main/java/org/apache/rat/report/ConfigurationReport.java @@ -19,6 +19,7 @@ package org.apache.rat.report; import java.io.IOException; +import java.lang.reflect.InvocationTargetException; import java.util.Collection; import java.util.HashSet; import java.util.List; @@ -33,8 +34,10 @@ import org.apache.commons.lang3.StringUtils; import org.apache.rat.ReportConfiguration; import org.apache.rat.api.RatException; +import org.apache.rat.config.parameters.Component; import org.apache.rat.config.parameters.Component.Type; import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; import org.apache.rat.configuration.MatcherBuilderTracker; import org.apache.rat.configuration.XMLConfigurationReader; import org.apache.rat.configuration.builders.MatcherRefBuilder; @@ -77,7 +80,7 @@ public void startReport() throws RatException { if (!licenses.isEmpty()) { writer.openElement(XMLConfigurationReader.LICENSES); for (ILicense license : licenses) { - writeDescription(license.getDescription()); + writeDescription(license.getDescription(), license); } writer.closeElement();// LICENSES } @@ -117,86 +120,146 @@ private void writeFamily(ILicenseFamily family) throws RatException { } } - private void writeDescriptions(Collection descriptions) throws RatException { + private void writeDescriptions(Collection descriptions, Component component) throws RatException { for (Description description : descriptions) { - writeDescription(description); + writeDescription(description, component); } } - private void writeChildren(Description description) throws RatException, IOException { - writeDescriptions(description.childrenOfType(Type.Parameter)); - writeDescriptions(description.childrenOfType(Type.Text)); - writeDescriptions(description.childrenOfType(Type.Matcher)); - writeDescriptions(description.childrenOfType(Type.License)); + private void writeChildren(Description description, Component component) throws RatException, IOException { + writeDescriptions(description.childrenOfType(Type.Parameter), component); + writeDescriptions(description.childrenOfType(Type.Unlabled), component); + writeDescriptions(description.childrenOfType(Type.Matcher), component); + writeDescriptions(description.childrenOfType(Type.License), component); } - private void writeDescription(Description description) throws RatException { - if (description == null) { - return; + private void writeComment(Description description) throws IOException { + if (StringUtils.isNotBlank(description.getDescription())) { + writer.comment(description.getDescription()); } + } + + private void writeContent(Description description, Component component) throws IOException { + String paramValue = description.getParamValue(component); + if (paramValue != null) { + writer.content(paramValue); + } + } + + private void writeAttribute(Description description, Component component) throws IOException { + String paramValue = description.getParamValue(component); + if (paramValue != null) { + writer.attribute(description.getCommonName(), paramValue); + } + } + + private void writeDescription(Description description, Component component) throws RatException { try { switch (description.getType()) { case Matcher: // see if id was registered Optional id = description.childrenOfType(Type.Parameter).stream().filter(i -> XMLConfigurationReader.ATT_ID.equals(i.getCommonName())).findFirst(); if (id.isPresent()) { - String idStr = id.get().getParamValue(); - if (matchers.contains(idStr)) { - description = new MatcherRefBuilder.IHeaderMatcherProxy(id.get().getParamValue(),null).getDescription(); + String idValue = id.get().getParamValue(component); + // if we have seen the ID before just put a reference to the other one. + if (matchers.contains(idValue.toString())) { + component = new MatcherRefBuilder.IHeaderMatcherProxy(idValue.toString(), null); + description = component.getDescription(); } else { - matchers.add(idStr); + matchers.add(idValue.toString()); } } - if (StringUtils.isNotBlank(description.getDescription())) { - writer.comment(description.getDescription()); - } + writeComment(description); writer.openElement(description.getCommonName()); - writeChildren(description); + writeChildren(description, component); writer.closeElement(); break; - case License: + case License: writer.openElement(XMLConfigurationReader.LICENSE); - List lst = description.childrenOfType(Type.Parameter).stream().filter(d -> !d.getCommonName().equals("notes")).collect(Collectors.toList()); - writeDescriptions(lst); - - lst = description.childrenOfType(Type.Parameter).stream().filter(d -> !d.getCommonName().equals("notes")).collect(Collectors.toList()); - if (!lst.isEmpty()) { - if (StringUtils.isNotBlank(lst.get(0).getDescription())) { - writer.comment(lst.get(0).getDescription()); - } - for (Description note : lst) { - writer.openElement(note.getCommonName()); - writer.content(description.getParamValue()); - writer.closeElement(); - } + Description notes = null; + for (Description desc : description.childrenOfType(Component.Type.Parameter)) { + if (desc.getCommonName().equals("notes")) { + notes = desc; + } else { + writeAttribute(desc, component); + } } - writeDescriptions(description.childrenOfType(Type.Matcher)); - writeDescriptions(description.childrenOfType(Type.License)); - writeChildren(description); + for (Description desc : description.childrenOfType(Component.Type.BuilderParam)) { + if (desc.getCommonName().equals("family")) { + try { + ILicenseFamily family = (ILicenseFamily) desc.getter(component.getClass()).invoke(component); + if (family != null) { + writer.attribute("family", family.getFamilyCategory().trim()); + } + } catch (NoSuchMethodException | IllegalAccessException | IllegalArgumentException | InvocationTargetException | SecurityException e) { + configuration.getLog().error(e.toString()); + } + } + } + // end of attributes + if (notes != null && StringUtils.isNotBlank(notes.getParamValue(component))) { + writeComment(notes); + writer.openElement(notes.getCommonName()); + writeContent(notes, component); + writer.closeElement(); + } + for (Description desc : description.childrenOfType(Component.Type.Unlabled)) { + writeDescription(desc, component); + } + //writeDescriptions(description.childrenOfType(Component.Type.Matcher), component); + //writeDescriptions(description.childrenOfType(Component.Type.License), component); writer.closeElement(); break; case Parameter: if ("id".equals(description.getCommonName())) { try { + String idValue = description.getParamValue(component); // if a UUID skip it. - UUID.fromString(description.getParamValue()); - return; + if (idValue != null) { + UUID.fromString(idValue.toString()); + return; + } } catch (IllegalArgumentException expected) { // do nothing. } } - String paramValue = description.getParamValue(); - if (paramValue != null) { - writer.attribute(description.getCommonName(), paramValue); + writeAttribute(description, component); + break; + case Unlabled: + try { + Object obj = description.getter(component.getClass()).invoke(component); + if (obj instanceof Iterable) { + for (Object o2 : (Iterable)obj) { + processUnlabled(o2); + } + } else { + processUnlabled(obj); + } + } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException + | NoSuchMethodException | SecurityException | RatException e) { + configuration.getLog().error(e.getMessage()); } break; - case Text: - writer.content(description.getParamValue()); + case BuilderParam: + // ignore; break; } } catch (IOException e) { throw new RatException(e); } } + + private void processUnlabled(Object obj) throws RatException, IOException { + if (obj instanceof Component) { + Description d = DescriptionBuilder.build(obj); + if (d != null) { + writeDescription( d, (Component)obj ); + } + } else { + if (obj != null) { + writer.content(obj.toString()); + } + } + } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java index c456b1e3a..17e4c2a8a 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/config/parameters/DescriptionBuilderTest.java @@ -18,7 +18,7 @@ public void matcherMapBuildTest() { assertEquals(Component.Type.Matcher, underTest.getType()); assertEquals("copyright", underTest.getCommonName()); assertNotNull(underTest.getDescription()); - assertNull(underTest.getParamValue()); + assertNull(underTest.getParamValue(null)); assertEquals(4,underTest.getChildren().size()); assertTrue(underTest.getChildren().containsKey("id")); assertTrue(underTest.getChildren().containsKey("start")); @@ -29,7 +29,7 @@ public void matcherMapBuildTest() { assertEquals(Component.Type.Matcher, underTest.getType()); assertEquals("all", underTest.getCommonName()); assertNotNull(underTest.getDescription()); - assertNull(underTest.getParamValue()); + assertNull(underTest.getParamValue(null)); assertEquals(2,underTest.getChildren().size()); assertTrue(underTest.getChildren().containsKey("id")); assertTrue(underTest.getChildren().containsKey("enclosed")); diff --git a/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java b/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java index 5ab68f036..5d17d1f1d 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/configuration/ConfigurationReaderTest.java @@ -110,14 +110,9 @@ public void descriptionTest() throws NoSuchMethodException, SecurityException { IHeaderMatcher.Builder builder = MatcherBuilderTracker.getMatcherBuilder("copyright"); Description desc = DescriptionBuilder.buildMap(builder.builtClass()); - print(desc); + System.out.println( desc ); } - private void print(Description desc) { - System.out.println( String.format( "T:%s N:%s V:%s", desc.getType(), desc.getCommonName(), desc.getParamValue())); - System.out.println( " "+desc.getDescription()); - desc.getChildren().values().forEach(this::print); - } } diff --git a/apache-rat-core/src/test/java/org/apache/rat/configuration/builders/TextBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/configuration/builders/TextBuilderTest.java new file mode 100644 index 000000000..d7980533c --- /dev/null +++ b/apache-rat-core/src/test/java/org/apache/rat/configuration/builders/TextBuilderTest.java @@ -0,0 +1,92 @@ +package org.apache.rat.configuration.builders; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.lang.reflect.InvocationTargetException; +import java.util.Collection; +import java.util.Map; +import java.util.HashMap; + +import org.apache.rat.analysis.matchers.FullTextMatcher; +import org.apache.rat.analysis.matchers.SimpleTextMatcher; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; +import org.junit.jupiter.api.Test; + +public class TextBuilderTest { + + Map attributes; + + TextBuilderTest() { + attributes = new HashMap<>(); + attributes.put("id", "IDValue"); + } + + @Test + public void fullTextMatcherTest() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException { + TextBuilder underTest = new TextBuilder(); + attributes.put("id", "IDValue"); + + Description description = DescriptionBuilder.buildMap(underTest.builtClass()); + description.setChildren(underTest, attributes); + description.setUnlabledText(underTest, "example text"); + + SimpleTextMatcher m = underTest.build(); + assertEquals("example text", m.getText()); + assertEquals("IDValue", m.getId()); + assertEquals(FullTextMatcher.class, m.getClass()); + + boolean foundText = false; + for (Description d : description.childrenOfType(Component.Type.Unlabled)) { + if (!d.isCollection()) { + assertEquals("example text", d.getter(m.getClass()).invoke(m)); + foundText = true; + } + } + assertTrue(foundText); + foundText = false; + for (Description d : description.childrenOfType(Component.Type.Parameter)) { + if (!d.isCollection()) { + assertEquals("IDValue", d.getter(m.getClass()).invoke(m)); + foundText = true; + } + } + assertTrue(foundText); + + } + + @Test + public void simpleTextMatcherTest() throws NoSuchMethodException, SecurityException, IllegalAccessException, + IllegalArgumentException, InvocationTargetException { + TextBuilder underTest = new TextBuilder(); + + Description description = DescriptionBuilder.buildMap(underTest.builtClass()); + description.setChildren(underTest, attributes); + description.setUnlabledText(underTest, "exampletext"); + + SimpleTextMatcher m = underTest.build(); + assertEquals("exampletext", m.getText()); + assertEquals(SimpleTextMatcher.class, m.getClass()); + + boolean foundText = false; + for (Description d : description.childrenOfType(Component.Type.Unlabled)) { + if (!d.isCollection()) { + assertEquals("exampletext", d.getter(m.getClass()).invoke(m)); + foundText = true; + } + } + assertTrue(foundText); + foundText = false; + for (Description d : description.childrenOfType(Component.Type.Parameter)) { + if (!d.isCollection()) { + assertEquals("IDValue", d.getter(m.getClass()).invoke(m)); + foundText = true; + } + } + assertTrue(foundText); + } + +} diff --git a/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java b/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java index 41a2cec99..a6c8eaf02 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/license/SimpleLicenseTest.java @@ -23,7 +23,7 @@ public void descriptionTest() { assertEquals(Component.Type.License, underTest.getType()); assertEquals("My testing license", underTest.getCommonName()); assertEquals("", underTest.getDescription()); - assertNull(underTest.getParamValue()); + assertNull(underTest.getParamValue(lic)); Map children = underTest.getChildren(); assertTrue(children.containsKey("id")); assertTrue(children.containsKey("name")); diff --git a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java index 5a0ff785a..1ba685d98 100644 --- a/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java +++ b/apache-rat-core/src/test/java/org/apache/rat/report/ConfigurationReportTest.java @@ -20,12 +20,15 @@ import java.io.IOException; import java.io.StringWriter; +import java.net.URL; import org.apache.rat.report.xml.writer.impl.base.XmlWriter; import org.apache.rat.report.xml.writer.IXmlWriter; import org.apache.rat.Defaults; import org.apache.rat.ReportConfiguration; import org.apache.rat.api.RatException; +import org.apache.rat.configuration.ConfigurationReaderTest; +import org.apache.rat.configuration.XMLConfigurationReader; import org.apache.rat.license.LicenseSetFactory.LicenseFilter; import org.apache.rat.utils.DefaultLog; import org.junit.jupiter.api.Test; @@ -35,9 +38,13 @@ public class ConfigurationReportTest { @Test public void testAll() throws RatException, IOException { + ReportConfiguration reportConfiguration = new ReportConfiguration(DefaultLog.INSTANCE); reportConfiguration.listFamilies(LicenseFilter.all); reportConfiguration.listLicenses(LicenseFilter.all); + + reportConfiguration.setFrom(Defaults.builder().build()); + StringWriter sw = new StringWriter(); IXmlWriter writer = new XmlWriter(sw); diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/License.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/License.java index ac17c2b09..da9c1bc98 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/License.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/License.java @@ -32,9 +32,6 @@ public class License extends EnclosingMatcher { @Parameter(required = false) private String notes; - @Parameter(required = false) - private String derivedFrom; - @Parameter(required = true) private String id; @@ -53,7 +50,7 @@ protected void setMatcher(IHeaderMatcher.Builder builder) { } public ILicense build(SortedSet context) { - return builder.setDerivedFrom(derivedFrom).setLicenseFamilyCategory(family).setId(id) + return builder.setLicenseFamilyCategory(family).setId(id) .setName(name).setNotes(notes).build(context); } diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Regex.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Regex.java index e8fedaf4a..46321cd9f 100644 --- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/Regex.java +++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/Regex.java @@ -27,7 +27,7 @@ public class Regex extends RegexBuilder { @Named("expr") public RegexBuilder setExpr(String exp) { System.out.format("Calling setText() with %s\n", exp); - return super.setExpr(exp); + return super.setPattern(exp); } public void set(String exp) { System.out.format("Calling set() with %s\n", exp); diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/License.java b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/License.java index 6d42088fc..d41ea0c52 100644 --- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/License.java +++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/License.java @@ -46,10 +46,6 @@ public void addNotes(String notes) { } - public void setDerivedFrom(String derivedFrom) { - builder.setDerivedFrom(derivedFrom); - } - public void setFamily(String licenseFamilyCategory) { builder.setLicenseFamilyCategory(licenseFamilyCategory); } diff --git a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Regex.java b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Regex.java index f212c4115..841f72c75 100644 --- a/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Regex.java +++ b/apache-rat-tasks/src/main/java/org/apache/rat/anttasks/Regex.java @@ -19,6 +19,7 @@ package org.apache.rat.anttasks; import org.apache.rat.analysis.IHeaderMatcher; +import org.apache.rat.analysis.matchers.SimpleRegexMatcher; import org.apache.rat.configuration.builders.RegexBuilder; public class Regex implements IHeaderMatcher.Builder { @@ -26,15 +27,15 @@ public class Regex implements IHeaderMatcher.Builder { private final RegexBuilder builder = new RegexBuilder(); public void setRegex(String pattern) { - builder.setExpr(pattern); + builder.setPattern(pattern); } - + public void addText(String pattern) { - builder.setExpr(pattern); + builder.setPattern(pattern); } @Override - public IHeaderMatcher build() { + public SimpleRegexMatcher build() { return builder.build(); } } diff --git a/apache-rat-tasks/src/test/java/org/example/Matcher.java b/apache-rat-tasks/src/test/java/org/example/Matcher.java index d5166d24a..59c82e5d9 100644 --- a/apache-rat-tasks/src/test/java/org/example/Matcher.java +++ b/apache-rat-tasks/src/test/java/org/example/Matcher.java @@ -18,8 +18,10 @@ import org.apache.rat.analysis.IHeaders; import org.apache.rat.analysis.matchers.AbstractSimpleMatcher; -import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.Component; +import org.apache.rat.config.parameters.ConfigComponent; +@ConfigComponent(type = Component.Type.Matcher, name = "myCustomMatcher", desc = "Custom matcher example") public class Matcher extends AbstractSimpleMatcher { public Matcher() { super("MyCustomMatcher"); @@ -29,10 +31,4 @@ public Matcher() { public boolean matches(IHeaders headers) { return true; } - - @Override - public Inspector getInspector() { - return AbstractInspector.matcher("MyCustomMatcher", getId(), null); - } - } From f56ec9ed5fb3fcc8328db5b924727cc848eaf6f9 Mon Sep 17 00:00:00 2001 From: Claude Warren Date: Wed, 27 Mar 2024 11:24:54 +0100 Subject: [PATCH 30/77] added Documentation class to dump text based documentation about the Components --- .../java/org/apache/rat/Documentation.java | 146 ++++++++++++++++++ .../src/main/java/org/apache/rat/Report.java | 54 ++++++- .../rat/config/parameters/Description.java | 6 +- .../config/parameters/DescriptionBuilder.java | 9 +- .../rat/configuration/LicenseReader.java | 2 + .../rat/configuration/MatcherReader.java | 1 + .../configuration/XMLConfigurationReader.java | 2 + .../builders/ChildContainerBuilder.java | 2 +- .../rat/report/ConfigurationReport.java | 6 +- .../rat/analysis/matchers/AndMatcherTest.java | 8 +- .../parameters/DescriptionBuilderTest.java | 21 ++- .../builders/TextBuilderTest.java | 22 ++- .../apache/rat/license/SimpleLicenseTest.java | 19 +++ .../rat/report/ConfigurationReportTest.java | 45 ++++-- .../apache/rat/report/xml/XmlReportTest.java | 2 +- 15 files changed, 310 insertions(+), 35 deletions(-) create mode 100644 apache-rat-core/src/main/java/org/apache/rat/Documentation.java diff --git a/apache-rat-core/src/main/java/org/apache/rat/Documentation.java b/apache-rat-core/src/main/java/org/apache/rat/Documentation.java new file mode 100644 index 000000000..976453ddd --- /dev/null +++ b/apache-rat-core/src/main/java/org/apache/rat/Documentation.java @@ -0,0 +1,146 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ +package org.apache.rat; + +import java.io.IOException; +import java.io.Writer; +import java.lang.reflect.InvocationTargetException; +import java.util.Map; + +import org.apache.commons.cli.HelpFormatter; +import org.apache.commons.cli.Options; +import org.apache.rat.config.parameters.Description; +import org.apache.rat.config.parameters.DescriptionBuilder; +import org.apache.rat.configuration.MatcherBuilderTracker; +import org.apache.rat.configuration.builders.AbstractBuilder; +import org.apache.rat.license.ILicense; +import org.apache.rat.license.ILicenseFamily; +import org.apache.rat.license.LicenseSetFactory.LicenseFilter; + +/** + * Generates text based documentation for Licenses, LicenceFamilies, and Matchers. + * + * Utilizes the same command line as the CLI based Report client so that additional licenses, etc. can be added. + * + */ +public class Documentation { + + private static final String INDENT = " "; + + private Documentation() { + } + + public static void output(ReportConfiguration cfg, Writer writer) throws IOException { + writer.write(String.format("%n>>>> LICENSES <<<<%n%n")); + for (ILicense l : cfg.getLicenses(LicenseFilter.all)) { + printLicense(l, writer); + } + + writer.write(String.format("%n>>>> MATCHERS (Datatype IHeaderMatcher) <<<<%n%n")); + for (Class mClazz : MatcherBuilderTracker.INSTANCE.getClasses()) { + try { + AbstractBuilder builder = mClazz.getConstructor().newInstance(); + printMatcher(DescriptionBuilder.buildMap(builder.builtClass()), writer); + } catch (NoSuchMethodException | SecurityException | InstantiationException | IllegalAccessException + | IllegalArgumentException | InvocationTargetException e) { + throw new ConfigurationException( + String.format("Can not instantiate matcher builder %s ", mClazz.getName()), e); + } + } + + writer.write(String.format("%n>>>> FAMILIES (Datatype ILicenseFamily) <<<<%n%n")); + for (ILicenseFamily family : cfg.getLicenseFamilies(LicenseFilter.all)) { + printFamily(family, writer); + } + } + + private static void printFamily(ILicenseFamily family, Writer writer) throws IOException { + writer.write(String.format("'%s' - %s%n", family.getFamilyCategory().trim(), family.getFamilyName())); + } + + private static void printMatcher(Description matcher, Writer writer) throws IOException { + writer.write(String.format("'%s' - %s%n", matcher.getCommonName(), matcher.getDescription())); + printChildren(1, matcher.getChildren(), writer); + + } + + private static void printLicense(ILicense license, Writer writer) throws IOException { + Description dLicense = license.getDescription(); + writer.write(String.format("'%s' - %s %n", dLicense.getCommonName(), dLicense.getDescription())); + printChildren(1, dLicense.getChildren(), writer); + } + + private static void writeIndent(int indent, Writer writer) throws IOException { + for (int i = 0; i < indent; i++) { + writer.write(INDENT); + } + } + + private static void printChildren(int indent, Map children, Writer writer) throws IOException { + for (Description d : children.values()) { + writeIndent(indent, writer); + switch (d.getType()) { + case Parameter: + case BuilderParam: + writer.write(String.format("'%s' %s (Datatype %s%s)%n", d.getCommonName(), d.getDescription(), + d.isCollection() ? "Collection of " : "", d.getChildType().getSimpleName())); + break; + case Unlabled: + writer.write(String.format("'%s name' %s (Datatype %s%s)%n", d.getCommonName(), d.getDescription(), + d.isCollection() ? "Collection of " : "", d.getChildType().getSimpleName())); + break; + case License: + // do noting + break; + case Matcher: + writeIndent(indent + 1, writer); + writer.write(String.format("%s %s %n", d.isCollection() ? "Collection of " : "A ", + d.getChildType().getSimpleName())); + printChildren(indent + 2, d.getChildren(), writer); + break; + } + } + } + + /** + * Creates the documentation. Writes to the outpus specified by the -o or --out option. Defaults to System.out. + * @param args the arguments. Try --help for help. + * @throws IOException on error + */ + public static void main(String[] args) throws IOException { + ReportConfiguration config = Report.parseCommands(args, Documentation::printUsage, true); + if (config != null) { + try (Writer writer = config.getWriter().get()) { + Documentation.output(config, writer); + } + } + } + + private static void printUsage(Options opts) { + HelpFormatter f = new HelpFormatter(); + f.setOptionComparator(new Report.OptionComparator()); + f.setWidth(120); + String header = "\nAvailable options"; + String footer = ""; + String cmdLine = String.format("java -jar apache-rat/target/apache-rat-CURRENT-VERSION.jar %s [options]", + Documentation.class.getName()); + f.printHelp(cmdLine, header, opts, footer, false); + System.exit(0); + } +} 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 f6e03b8d7..d59450eac 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 @@ -31,6 +31,7 @@ import java.util.Arrays; import java.util.Comparator; import java.util.List; +import java.util.function.Consumer; import java.util.regex.PatternSyntaxException; import java.util.stream.Collectors; @@ -130,6 +131,33 @@ public class Report { * @throws Exception on error. */ public static void main(String[] args) throws Exception { + ReportConfiguration configuration = parseCommands(args, Report::printUsage); + if (configuration != null) { + configuration.validate(DefaultLog.INSTANCE::error); + Reporter.report(configuration); + } + } + + /** + * Parses the standard options to create a ReportConfiguraton. + * @param args the arguments to parse + * @param helpCmd the help command to run when necessary. + * @return a ReportConfiguration or null if Help was printed. + * @throws IOException on error. + */ + public static ReportConfiguration parseCommands(String[] args, Consumer helpCmd) throws IOException { + return parseCommands(args, helpCmd, false); + } + + /** + * Parses the standard options to create a ReportConfiguraton. + * @param args the arguments to parse + * @param helpCmd the help command to run when necessary. + * @param noArgs If true then the commands do not need extra arguments + * @return a ReportConfiguration or null if Help was printed. + * @throws IOException on error. + */ + public static ReportConfiguration parseCommands(String[] args, Consumer helpCmd, boolean noArgs) throws IOException { Options opts = buildOptions(); CommandLine cl; try { @@ -138,7 +166,7 @@ public static void main(String[] args) throws Exception { DefaultLog.INSTANCE.error(e.getMessage()); DefaultLog.INSTANCE.error("Please use the \"--help\" option to see a list of valid commands and options"); System.exit(1); - return; // dummy return (won't be reached) to avoid Eclipse complaint about possible NPE + return null; // dummy return (won't be reached) to avoid Eclipse complaint about possible NPE // for "cl" } @@ -152,14 +180,20 @@ public static void main(String[] args) throws Exception { } } if (cl.hasOption(HELP)) { - printUsage(opts); + helpCmd.accept(opts); + return null; } - args = cl.getArgs(); - if (args == null || args.length != 1) { - printUsage(opts); + if (!noArgs) { + args = cl.getArgs(); + if (args == null || args.length != 1) { + helpCmd.accept(opts); + return null; + } } else { - ReportConfiguration configuration = createConfiguration(args[0], cl); + args = new String[] {null}; + } +/* ReportConfiguration configuration = createConfiguration(args[0], cl); configuration.validate(DefaultLog.INSTANCE::error); boolean dryRun = false; @@ -183,6 +217,8 @@ public static void main(String[] args) throws Exception { new Reporter(configuration).output(); } } +*/ ReportConfiguration configuration = createConfiguration(args[0], cl); + return configuration; } static ReportConfiguration createConfiguration(String baseDirectory, CommandLine cl) throws IOException { @@ -258,7 +294,9 @@ static ReportConfiguration createConfiguration(String baseDirectory, CommandLine } Defaults defaults = defaultBuilder.build(); configuration.setFrom(defaults); - configuration.setReportable(getDirectory(baseDirectory, configuration)); + if (baseDirectory != null) { + configuration.setReportable(getDirectory(baseDirectory, configuration)); + } return configuration; } @@ -431,7 +469,7 @@ private static IReportable getDirectory(String baseDirectory, ReportConfiguratio /** * This class implements the {@code Comparator} interface for comparing Options. */ - private static class OptionComparator implements Comparator