From 2baba8a594bc9f9ac057d357a3f088341ef094cc Mon Sep 17 00:00:00 2001
From: "P. Ottlinger"
Date: Sun, 8 Dec 2024 23:47:11 +0100
Subject: [PATCH 01/41] RAT-379: Groovify proposed solution and shorten log
output during build
---
.../copyResourcesFromParentProject.groovy | 69 ++++++++++---------
1 file changed, 35 insertions(+), 34 deletions(-)
diff --git a/apache-rat-core/src/main/build-grv/copyResourcesFromParentProject.groovy b/apache-rat-core/src/main/build-grv/copyResourcesFromParentProject.groovy
index be232db9e..e8501d6c1 100644
--- a/apache-rat-core/src/main/build-grv/copyResourcesFromParentProject.groovy
+++ b/apache-rat-core/src/main/build-grv/copyResourcesFromParentProject.groovy
@@ -16,50 +16,51 @@
*/
// Copy a set of resource files from the parent project to target/classes/META-INF,
-// so that they become a part of the generated jar file. See RAT-379.
+// so that they become a part of the generated jar file. See RAT-379 for details.
-import java.io.FileNotFoundException;
-import java.nio.file.attribute.FileTime;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.nio.file.Paths;
-import java.nio.file.StandardCopyOption;
+import java.nio.file.attribute.FileTime
+import java.nio.file.Files
+import java.nio.file.Path
+import java.nio.file.Paths
+import java.nio.file.StandardCopyOption
+
+final Path sourceDir = Paths.get("${sourceDir}")
+final Path targetDir = Paths.get("${targetDir}")
-final Path sourceDir = Paths.get("${sourceDir}");
-final Path targetDir = Paths.get("${targetDir}");
if (!Files.isDirectory(sourceDir)) {
- final String msg = "Source directory not found: " + sourceDir.toAbsolutePath();
- log.error(msg);
- throw new FileNotFoundException(msg);
+ final String msg = "Source directory not found: " + sourceDir.toAbsolutePath()
+ System.err.println(msg)
+ throw new FileNotFoundException(msg)
}
-log.debug("copyResourcesFromParent: Using source directory " + sourceDir + ", resolved to " + sourceDir.toAbsolutePath());
-log.debug("copyResourcesFromParent: Using target directory " + targetDir + ", resolved to " + targetDir.toAbsolutePath());
-Files.createDirectories(targetDir);
-for (StringTokenizer st = new StringTokenizer("${filesToCopy}", ","); st.hasMoreTokens(); ) {
- final String token = st.nextToken();
- final Path sourceFile = sourceDir.resolve(token);
+
+// System.out.println("copyResourcesFromParent: Using source directory " + sourceDir + ", resolved to " + sourceDir.toAbsolutePath())
+// System.out.println("copyResourcesFromParent: Using target directory " + targetDir + ", resolved to " + targetDir.toAbsolutePath())
+Files.createDirectories(targetDir)
+
+for (StringTokenizer st = new StringTokenizer("${filesToCopy}", ","); st.hasMoreTokens(); ) {
+ final String token = st.nextToken()
+ final Path sourceFile = sourceDir.resolve(token)
if (!Files.isRegularFile(sourceFile)) {
- final String msg = "Source file " + token + " not found in source directory " + sourceDir;
- log.error("copyResourcesFromParent: " + msg);
- log.error("copyResourcesFromParent: A possible reason is, that you did clone only the apache-rat-core subproject from Git.");
- throw new FileNotFoundException(msg);
+ final String msg = "Source file " + token + " not found in source directory " + sourceDir
+ System.err.println("copyResourcesFromParent: " + msg)
+ System.err.println("copyResourcesFromParent: A possible reason is, that you did clone only the apache-rat-core subproject from Git.")
+ throw new FileNotFoundException(msg)
}
- final Path targetFile = targetDir.resolve(token);
- final boolean replacing = Files.isRegularFile(targetFile);
+ final Path targetFile = targetDir.resolve(token)
+ final boolean replacing = Files.isRegularFile(targetFile)
if (replacing) {
- final FileTime sourceTime = Files.getLastModifiedTime(sourceFile);
- final FileTime targetTime = Files.getLastModifiedTime(targetFile);
- if (sourceTime != null && targetTime != null && sourceTime.compareTo(targetTime) >= 0) {
- log.debug("copyResourcesFromParent: Skipping source file "
- + sourceFile + ", because target file " + targetFile + " appears to be uptodate.");
- continue;
+ final FileTime sourceTime = Files.getLastModifiedTime(sourceFile)
+ final FileTime targetTime = Files.getLastModifiedTime(targetFile)
+ if (sourceTime != null && targetTime != null && sourceTime >= targetTime) {
+ System.out.println("Skipping " + sourceFile + ", as target " + targetFile + " appears to be up-to-date already.")
+ continue
}
}
- log.debug("copyResourcesFromParent: Copying source file " + sourceFile
- + " to target file " + targetFile);
+ System.out.println("Copying " + sourceFile
+ + " to " + targetFile)
if (replacing) {
- Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING);
+ Files.copy(sourceFile, targetFile, StandardCopyOption.REPLACE_EXISTING)
} else {
- Files.copy(sourceFile, targetFile);
+ Files.copy(sourceFile, targetFile)
}
}
From ce21f2add7c036b916e8c6f094310eeed9662820 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 16 Dec 2024 00:55:06 +0000
Subject: [PATCH 02/41] Bump org.apache.commons:commons-text from 1.12.0 to
1.13.0
Bumps org.apache.commons:commons-text from 1.12.0 to 1.13.0.
---
updated-dependencies:
- dependency-name: org.apache.commons:commons-text
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 025a6130b..0ad4c8ab8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -139,7 +139,7 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.commonscommons-text
- 1.12.0
+ 1.13.0org.apache.commons
From 9b3c4b0033607efbd257b1dbaef36502f09c0ff0 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 17 Dec 2024 00:22:52 +0000
Subject: [PATCH 03/41] Bump org.junit:junit-bom from 5.11.3 to 5.11.4
Bumps [org.junit:junit-bom](https://github.com/junit-team/junit5) from 5.11.3 to 5.11.4.
- [Release notes](https://github.com/junit-team/junit5/releases)
- [Commits](https://github.com/junit-team/junit5/compare/r5.11.3...r5.11.4)
---
updated-dependencies:
- dependency-name: org.junit:junit-bom
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 0ad4c8ab8..4909a184a 100644
--- a/pom.xml
+++ b/pom.xml
@@ -149,7 +149,7 @@ agnostic home for software distribution comprehension and audit tools.
org.junitjunit-bom
- 5.11.3
+ 5.11.4pomimport
From 4bf8b7772f27666a8147cd53db519b65d9ac70a2 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Fri, 20 Dec 2024 00:43:19 +0000
Subject: [PATCH 04/41] Bump org.assertj:assertj-core from 3.26.3 to 3.27.0
Bumps [org.assertj:assertj-core](https://github.com/assertj/assertj) from 3.26.3 to 3.27.0.
- [Release notes](https://github.com/assertj/assertj/releases)
- [Commits](https://github.com/assertj/assertj/compare/assertj-build-3.26.3...assertj-build-3.27.0)
---
updated-dependencies:
- dependency-name: org.assertj:assertj-core
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 4909a184a..0fa75e127 100644
--- a/pom.xml
+++ b/pom.xml
@@ -198,7 +198,7 @@ agnostic home for software distribution comprehension and audit tools.
org.assertjassertj-core
- 3.26.3
+ 3.27.0test
From 61dd8c5cf8b689116333cd8a79815794f97fb049 Mon Sep 17 00:00:00 2001
From: "P. Ottlinger"
Date: Wed, 1 Jan 2025 22:15:36 +0100
Subject: [PATCH 05/41] Happy new year
---
src/site/site.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/src/site/site.xml b/src/site/site.xml
index 76443f91f..a64c73555 100644
--- a/src/site/site.xml
+++ b/src/site/site.xml
@@ -128,7 +128,7 @@
-
*/
-public final class DocumentName implements Comparable {
- /** The list of all roots on the file system. */
- static final Set ROOTS = new HashSet<>();
- /** {@code True} if the file system on which we are operating is case-sensitive. */
- public static final boolean FS_IS_CASE_SENSITIVE;
+public class DocumentName implements Comparable {
/** The full name for the document. */
private final String name;
/** The name of the base directory for the document. */
- private final String baseName;
- /** The directory separator for this document. */
- private final String dirSeparator;
- /** The case-sensitive flag */
- private final boolean isCaseSensitive;
+ private final DocumentName baseName;
+ /** The file system info for this document. */
+ private final FSInfo fsInfo;
/** The root for the DocumentName. May be empty but not null. */
private final String root;
- // determine the case sensitivity of the file system we are operating on.
- static {
- boolean fsSensitive = true;
- File f = null;
+ /**
+ * Determines if the file system is case-sensitive.
+ * @param fileSystem the file system to check
+ * @return {@code true} if the file system is case-sensitive.
+ */
+ private static boolean isCaseSensitive(final FileSystem fileSystem) {
+ boolean isCaseSensitive = false;
+ Path nameSet = null;
+ Path filea = null;
+ Path fileA = null;
try {
- Path p = Files.createTempDirectory("NameSet");
- f = p.toFile();
- fsSensitive = !new File(f, "a").equals(new File(f, "A"));
- } catch (IOException e) {
- fsSensitive = true;
- } finally {
- if (f != null) {
- try {
- FileUtils.deleteDirectory(f);
- } catch (IOException e) {
- DefaultLog.getInstance().warn("Unable to delete temporary directory: " + f, e);
+ try {
+ Path root = fileSystem.getPath("");
+ nameSet = Files.createTempDirectory(root, "NameSet");
+ filea = nameSet.resolve("a");
+ fileA = nameSet.resolve("A");
+ Files.createFile(filea);
+ Files.createFile(fileA);
+ isCaseSensitive = true;
+ } catch (IOException e) {
+ // do nothing
+ } finally {
+ if (filea != null) {
+ Files.deleteIfExists(filea);
+ }
+ if (fileA != null) {
+ Files.deleteIfExists(fileA);
+ }
+ if (nameSet != null) {
+ Files.deleteIfExists(nameSet);
}
}
+ } catch (IOException e) {
+ // do nothing.
}
- FS_IS_CASE_SENSITIVE = fsSensitive;
-
- // determine all the roots on the file system(s).
- File[] roots = File.listRoots();
- if (roots != null) {
- for (File root : roots) {
- String name = root.getPath();
- ROOTS.add(name);
- }
- }
-
+ return isCaseSensitive;
}
/**
- * Creates a Builder with directory separator and case sensitivity based on the local file system.
+ * Creates a Builder with the default File system info.
* @return the Builder.
+ * @see FSInfo
*/
public static Builder builder() {
- return new Builder();
+ return new Builder(FSInfo.getDefault());
+ }
+
+ /**
+ * Creates a builder with the specified FSInfo instance.
+ * @param fsInfo the FSInfo to use for the builder.
+ * @return a new builder.
+ */
+ public static Builder builder(final FSInfo fsInfo) {
+ return new Builder(fsInfo);
+ }
+
+ /**
+ * Creates a builder for the specified file system.
+ * @param fileSystem the file system to create ethe builder on.
+ * @return a new builder.
+ */
+ public static Builder builder(final FileSystem fileSystem) {
+ return new Builder(fileSystem);
}
/**
- * Creates a builder from a File. The {@link #baseName} is set to the file name if it is a directory otherwise
- * it is set to the directory containing the file. The {@link #dirSeparator} is set from the file and
- * case sensitivity based on the local file system.
+ * Creates a builder from a File. The {@link #baseName} is set to the file name if it is a directory otherwise
+ * it is set to the directory containing the file.
* @param file The file to set defaults from.
* @return the Builder.
*/
@@ -131,26 +154,49 @@ public static Builder builder(final DocumentName documentName) {
* Builds the DocumentName from the builder.
* @param builder the builder to provide the values.
*/
- private DocumentName(final Builder builder) {
+ DocumentName(final Builder builder) {
this.name = builder.name;
- this.baseName = builder.baseName;
- this.dirSeparator = builder.dirSeparator;
- this.isCaseSensitive = builder.isCaseSensitive;
+ this.fsInfo = builder.fsInfo;
this.root = builder.root;
+ this.baseName = builder.sameNameFlag ? this : builder.baseName;
+ }
+
+ /**
+ * Creates a file from the document name.
+ * @return a new File object.
+ */
+ public File asFile() {
+ return new File(getName());
+ }
+
+ /**
+ * Creates a path from the document name.
+ * @return a new Path object.
+ */
+ public Path asPath() {
+ return Paths.get(name);
}
/**
* Creates a new DocumentName by adding the child to the current name.
+ * Resulting documentName will have the same base name.
* @param child the child to add (must use directory separator from this document name).
- * @return the new document name with the same {@link #baseName}, {@link #dirSeparator} and case sensitivity as
+ * @return the new document name with the same {@link #baseName}, directory sensitivity and case sensitivity as
* this one.
*/
public DocumentName resolve(final String child) {
- List parts = new ArrayList<>();
- parts.addAll(Arrays.asList(tokenize(name)));
- parts.addAll(Arrays.asList(tokenize(child)));
- String newName = String.join(dirSeparator, parts);
- return new Builder(this).setName(newName).build();
+ if (StringUtils.isBlank(child)) {
+ return this;
+ }
+ String separator = fsInfo.dirSeparator();
+ String pattern = separator.equals("/") ? child.replace('\\', '/') :
+ child.replace('/', '\\');
+
+ if (!pattern.startsWith(separator)) {
+ pattern = name + separator + pattern;
+ }
+
+ return new Builder(this).setName(pattern).build();
}
/**
@@ -158,7 +204,7 @@ public DocumentName resolve(final String child) {
* @return the fully qualified name of the document.
*/
public String getName() {
- return root + dirSeparator + name;
+ return root + fsInfo.dirSeparator() + name;
}
/**
@@ -166,7 +212,7 @@ public String getName() {
* @return the fully qualified basename of the document.
*/
public String getBaseName() {
- return root + dirSeparator + baseName;
+ return baseName.getName();
}
/**
@@ -182,7 +228,7 @@ public String getRoot() {
* @return the DocumentName for the basename of this document name.
*/
public DocumentName getBaseDocumentName() {
- return name.equals(baseName) ? this : builder(this).setName(baseName).build();
+ return baseName;
}
/**
@@ -190,7 +236,25 @@ public DocumentName getBaseDocumentName() {
* @return the directory separator.
*/
public String getDirectorySeparator() {
- return dirSeparator;
+ return fsInfo.dirSeparator();
+ }
+
+ /**
+ * Determines if the candidate starts with the root or separator strings.
+ * @param candidate the candidate ot check. If blank method will return {@code false}.
+ * @param root the root to check. If blank the root check is skipped.
+ * @param separator the separator to check. If blank the check is skipped.
+ * @return true if either the root or separator check returned {@code true}.
+ */
+ boolean startsWithRootOrSeparator(final String candidate, final String root, final String separator) {
+ if (StringUtils.isBlank(candidate)) {
+ return false;
+ }
+ boolean result = !StringUtils.isBlank(root) && candidate.startsWith(root);
+ if (!result) {
+ result = !StringUtils.isBlank(separator) && candidate.startsWith(separator);
+ }
+ return result;
}
/**
@@ -199,12 +263,13 @@ public String getDirectorySeparator() {
* @return the portion of the name that is not part of the base name.
*/
public String localized() {
- String result = name;
- if (result.startsWith(baseName)) {
- result = result.substring(baseName.length());
+ String result = getName();
+ String baseNameStr = baseName.getName();
+ if (result.startsWith(baseNameStr)) {
+ result = result.substring(baseNameStr.length());
}
- if (!result.startsWith(dirSeparator)) {
- result = dirSeparator + result;
+ if (!startsWithRootOrSeparator(result, getRoot(), fsInfo.dirSeparator())) {
+ result = fsInfo.dirSeparator() + result;
}
return result;
}
@@ -216,24 +281,26 @@ public String localized() {
* @return the portion of the name that is not part of the base name.
*/
public String localized(final String dirSeparator) {
- return String.join(dirSeparator, tokenize(localized()));
- }
+ String[] tokens = fsInfo.tokenize(localized());
+ if (tokens.length == 0) {
+ return dirSeparator;
+ }
+ if (tokens.length == 1) {
+ return dirSeparator + tokens[0];
+ }
- /**
- * Tokenizes the string based on the {@link #dirSeparator} of this DocumentName.
- * @param source the source to tokenize
- * @return the array of tokenized strings.
- */
- public String[] tokenize(final String source) {
- return source.split("\\Q" + dirSeparator + "\\E");
+ String modifiedRoot = dirSeparator.equals("/") ? root.replace('\\', '/') :
+ root.replace('/', '\\');
+ String result = String.join(dirSeparator, tokens);
+ return startsWithRootOrSeparator(result, modifiedRoot, dirSeparator) ? result : dirSeparator + result;
}
/**
- * Gets the last segment of the name. This is the part after the last {@link #dirSeparator}..
+ * Gets the last segment of the name. This is the part after the last directory separator.
* @return the last segment of the name.
*/
public String getShortName() {
- int pos = name.lastIndexOf(dirSeparator);
+ int pos = name.lastIndexOf(fsInfo.dirSeparator());
return pos == -1 ? name : name.substring(pos + 1);
}
@@ -242,7 +309,7 @@ public String getShortName() {
* @return {@code true} if the name is case-sensitive.
*/
public boolean isCaseSensitive() {
- return isCaseSensitive;
+ return fsInfo.isCaseSensitive();
}
/**
@@ -255,88 +322,239 @@ public String toString() {
}
@Override
- public int compareTo(final DocumentName o) {
- return FS_IS_CASE_SENSITIVE ? name.compareTo(o.name) : name.compareToIgnoreCase(o.name);
+ public int compareTo(final DocumentName other) {
+ return CompareToBuilder.reflectionCompare(this, other);
}
@Override
- public boolean equals(final Object o) {
- if (this == o) {
- return true;
- }
- if (o == null || getClass() != o.getClass()) {
- return false;
- }
- DocumentName that = (DocumentName) o;
- if (isCaseSensitive() == that.isCaseSensitive() && Objects.equals(dirSeparator, that.dirSeparator)) {
- return isCaseSensitive ? name.equalsIgnoreCase(that.name) : name.equals(that.name);
- }
- return false;
+ public boolean equals(final Object other) {
+ return EqualsBuilder.reflectionEquals(this, other);
}
@Override
public int hashCode() {
- return Objects.hash(name, dirSeparator, isCaseSensitive());
+ return HashCodeBuilder.reflectionHashCode(this);
+ }
+
+ /**
+ * The file system information needed to process document names.
+ */
+ public static class FSInfo implements Comparable {
+ /** The common name for the file system this Info represents. */
+ private final String name;
+ /** The separator between directory names. */
+ private final String separator;
+ /** The case-sensitivity flag. */
+ private final boolean isCaseSensitive;
+ /** The list of roots for the file system. */
+ private final List roots;
+
+ public static FSInfo getDefault() {
+ FSInfo result = (FSInfo) System.getProperties().get("FSInfo");
+ return result == null ?
+ new FSInfo("default", FileSystems.getDefault())
+ : result;
+ }
+ /**
+ * Constructor. Extracts the necessary data from the file system.
+ * @param fileSystem the file system to extract data from.
+ */
+ public FSInfo(final FileSystem fileSystem) {
+ this("anon", fileSystem);
+ }
+
+ /**
+ * Constructor. Extracts the necessary data from the file system.
+ * @param fileSystem the file system to extract data from.
+ */
+ public FSInfo(final String name, final FileSystem fileSystem) {
+ this.name = name;
+ this.separator = fileSystem.getSeparator();
+ this.isCaseSensitive = DocumentName.isCaseSensitive(fileSystem);
+ roots = new ArrayList<>();
+ fileSystem.getRootDirectories().forEach(r -> roots.add(r.toString()));
+ }
+
+ /**
+ * Gets the common name for the underlying file system.
+ * @return the common file system name.
+ */
+ @Override
+ public String toString() {
+ return name;
+ }
+
+ /**
+ * Constructor for virtual/abstract file systems for example the entry names within an archive.
+ * @param separator the separator string to use.
+ * @param isCaseSensitive the case-sensitivity flag.
+ * @param roots the roots for the file system.
+ */
+ FSInfo(final String name, final String separator, final boolean isCaseSensitive, final List roots) {
+ this.name = name;
+ this.separator = separator;
+ this.isCaseSensitive = isCaseSensitive;
+ this.roots = new ArrayList<>(roots);
+ }
+
+ /**
+ * Gets the directory separator.
+ * @return The directory separator.
+ */
+ public String dirSeparator() {
+ return separator;
+ }
+
+ /**
+ * Gets the case-sensitivity flag.
+ * @return the case-sensitivity flag.
+ */
+ public boolean isCaseSensitive() {
+ return isCaseSensitive;
+ }
+
+ /**
+ * Retrieves the root extracted from the name.
+ * @param name the name to extract the root from
+ * @return an optional containing the root or empty.
+ */
+ public Optional rootFor(final String name) {
+ for (String sysRoot : roots) {
+ if (name.startsWith(sysRoot)) {
+ return Optional.of(sysRoot);
+ }
+ }
+ return Optional.empty();
+ }
+
+ /**
+ * Tokenizes the string based on the directory separator of this DocumentName.
+ * @param source the source to tokenize.
+ * @return the array of tokenized strings.
+ */
+ public String[] tokenize(final String source) {
+ return source.split("\\Q" + dirSeparator() + "\\E");
+ }
+
+ /**
+ * Removes {@code .} and {@code ..} from filenames.
+ * @param pattern the file name pattern
+ * @return the normalized file name.
+ */
+ public String normalize(final String pattern) {
+ if (StringUtils.isBlank(pattern)) {
+ return "";
+ }
+ List parts = new ArrayList<>(Arrays.asList(tokenize(pattern)));
+ for (int i = 0; i < parts.size(); i++) {
+ String part = parts.get(i);
+ if (part.equals("..")) {
+ if (i == 0) {
+ throw new IllegalStateException("Unable to create path before root");
+ }
+ parts.set(i - 1, null);
+ parts.set(i, null);
+ } else if (part.equals(".")) {
+ parts.set(i, null);
+ }
+ }
+ return parts.stream().filter(Objects::nonNull).collect(Collectors.joining(dirSeparator()));
+ }
+
+ @Override
+ public int compareTo(final FSInfo other) {
+ return CompareToBuilder.reflectionCompare(this, other);
+ }
+
+ @Override
+ public boolean equals(final Object other) {
+ return EqualsBuilder.reflectionEquals(this, other);
+ }
+
+ @Override
+ public int hashCode() {
+ return HashCodeBuilder.reflectionHashCode(this);
+ }
}
/**
* The Builder for a DocumentName.
*/
public static final class Builder {
- /** The name for the document */
+ /** The name for the document. */
private String name;
- /** The base name for the document */
- private String baseName;
- /** The directory separator */
- private String dirSeparator;
- /** The case sensitivity flag */
- private boolean isCaseSensitive;
- /** The file system root */
+ /** The base name for the document. */
+ private DocumentName baseName;
+ /** The file system info. */
+ private final FSInfo fsInfo;
+ /** The file system root. */
private String root;
+ /** A flag for baseName same as this. */
+ private boolean sameNameFlag;
/**
* Create with default settings.
*/
- private Builder() {
- isCaseSensitive = FS_IS_CASE_SENSITIVE;
- dirSeparator = File.separator;
+ private Builder(final FSInfo fsInfo) {
+ this.fsInfo = fsInfo;
root = "";
}
+ /**
+ * Create with default settings.
+ */
+ private Builder(final FileSystem fileSystem) {
+ this(new FSInfo(fileSystem));
+ }
+
/**
* Create based on the file provided.
* @param file the file to base the builder on.
*/
private Builder(final File file) {
- this();
+ this(FSInfo.getDefault());
+ setName(file);
+ }
+
+ /**
+ * Used in testing.
+ * @param fsInfo the FSInfo for the file.
+ * @param file the file to process.
+ */
+ Builder(final FSInfo fsInfo, final File file) {
+ this(fsInfo);
setName(file);
- isCaseSensitive = FS_IS_CASE_SENSITIVE;
- dirSeparator = File.separator;
}
/**
* Create a Builder that clones the specified DocumentName.
* @param documentName the DocumentName to clone.
*/
- private Builder(final DocumentName documentName) {
+ Builder(final DocumentName documentName) {
this.root = documentName.root;
this.name = documentName.name;
this.baseName = documentName.baseName;
- this.isCaseSensitive = documentName.isCaseSensitive;
- this.dirSeparator = documentName.dirSeparator;
+ this.fsInfo = documentName.fsInfo;
+ }
+
+ /**
+ * Get the directory separator for this builder.
+ * @return the directory separator fo this builder.
+ */
+ public String directorySeparator() {
+ return fsInfo.dirSeparator();
}
/**
* Verify that the builder will build a proper DocumentName.
*/
private void verify() {
- Objects.requireNonNull(name, "Name cannot be null");
- Objects.requireNonNull(baseName, "Basename cannot be null");
- if (name.startsWith(dirSeparator)) {
- name = name.substring(dirSeparator.length());
+ Objects.requireNonNull(name, "Name must not be null");
+ if (name.startsWith(fsInfo.dirSeparator())) {
+ name = name.substring(fsInfo.dirSeparator().length());
}
- if (baseName.startsWith(dirSeparator)) {
- baseName = baseName.substring(dirSeparator.length());
+ if (!sameNameFlag) {
+ Objects.requireNonNull(baseName, "Basename must not be null");
}
}
@@ -346,58 +564,54 @@ private void verify() {
* @return this.
*/
public Builder setRoot(final String root) {
- this.root = root;
+ this.root = StringUtils.defaultIfBlank(root, "");
return this;
}
/**
- * Sets the name for this DocumentName. Will reset the root to the empty string.
+ * Sets the name for this DocumentName relative to the baseName.
+ * If the {@code name} is {@code null} an empty string is used.
*
- * To correctly parse the string it must either be the directory separator specified by
- * {@link File#separator} or must have been explicitly set by calling {@link #setDirSeparator(String)}
- * before making this call.
+ * To correctly parse the string it must use the directory separator specified by
+ * this Document.
*
- * @param name the name for this Document name.
+ * @param name the name for this Document name. Will be made relative to the baseName.
* @return this
*/
public Builder setName(final String name) {
- Pair pair = splitRoot(name, dirSeparator);
+ Pair pair = splitRoot(StringUtils.defaultIfBlank(name, ""));
if (this.root.isEmpty()) {
this.root = pair.getLeft();
}
- this.name = pair.getRight();
+ this.name = fsInfo.normalize(pair.getRight());
+ if (this.baseName != null && !baseName.name.isEmpty()) {
+ if (!this.name.startsWith(baseName.name)) {
+ this.name = this.name.isEmpty() ? baseName.name :
+ baseName.name + fsInfo.dirSeparator() + this.name;
+ }
+ }
return this;
}
- /**
- * Extracts the root/name pair from a file.
- * @param file the file to extract the root/name pair from.
- * @return the root/name pair.
- */
- static Pair splitRoot(final File file) {
- return splitRoot(file.getAbsolutePath(), File.separator);
- }
-
/**
* Extracts the root/name pair from a name string.
*
* Package private for testing.
*
* @param name the name to extract the root/name pair from.
- * @param dirSeparator the directory separator.
* @return the root/name pair.
*/
- static Pair splitRoot(final String name, final String dirSeparator) {
+ Pair splitRoot(final String name) {
String workingName = name;
- String root = "";
- for (String sysRoot : ROOTS) {
- if (workingName.startsWith(sysRoot)) {
- workingName = workingName.substring(sysRoot.length());
- if (!workingName.startsWith(dirSeparator)) {
- if (sysRoot.endsWith(dirSeparator)) {
- root = sysRoot.substring(0, sysRoot.length() - dirSeparator.length());
+ Optional maybeRoot = fsInfo.rootFor(name);
+ String root = maybeRoot.orElse("");
+ if (!root.isEmpty()) {
+ if (workingName.startsWith(root)) {
+ workingName = workingName.substring(root.length());
+ if (!workingName.startsWith(fsInfo.dirSeparator())) {
+ if (root.endsWith(fsInfo.dirSeparator())) {
+ root = root.substring(0, root.length() - fsInfo.dirSeparator().length());
}
- return ImmutablePair.of(root, workingName);
}
}
}
@@ -415,21 +629,24 @@ private void setEmptyRoot(final String root) {
}
/**
- * Sets the properties from the file. This method sets the {@link #root} if it is empty, and resets {@link #name},
- * {@link #dirSeparator} and {@link #baseName}.
+ * Sets the properties from the file. Will reset the baseName appropriately.
* @param file the file to set the properties from.
* @return this.
*/
public Builder setName(final File file) {
- Pair pair = splitRoot(file);
+ Pair pair = splitRoot(file.getAbsolutePath());
setEmptyRoot(pair.getLeft());
- this.name = pair.getRight();
- this.dirSeparator = File.separator;
- this.baseName = name;
- if (!file.isDirectory()) {
+ this.name = fsInfo.normalize(pair.getRight());
+ if (file.isDirectory()) {
+ sameNameFlag = true;
+ } else {
File p = file.getParentFile();
if (p != null) {
setBaseName(p);
+ } else {
+ Builder baseBuilder = new Builder(this.fsInfo).setName(this.directorySeparator());
+ baseBuilder.sameNameFlag = true;
+ setBaseName(baseBuilder.build());
}
}
return this;
@@ -439,17 +656,15 @@ public Builder setName(final File file) {
* Sets the baseName.
* Will set the root if it is not set.
*
- * To correctly parse the string it must either be the directory separator specified by
- * {@link File#separator} or must have been explicitly set by calling {@link #setDirSeparator(String)}
- * before making this call.
+ * To correctly parse the string it must use the directory separator specified by this builder.
*
* @param baseName the basename to use.
* @return this.
*/
public Builder setBaseName(final String baseName) {
- Pair pair = splitRoot(baseName, dirSeparator);
- setEmptyRoot(pair.getLeft());
- this.baseName = pair.getRight();
+ DocumentName.Builder builder = DocumentName.builder(fsInfo).setName(baseName);
+ builder.sameNameFlag = true;
+ setBaseName(builder);
return this;
}
@@ -460,7 +675,7 @@ public Builder setBaseName(final String baseName) {
* @return this.
*/
public Builder setBaseName(final DocumentName baseName) {
- this.baseName = baseName.getName();
+ this.baseName = baseName;
if (!baseName.getRoot().isEmpty()) {
this.root = baseName.getRoot();
}
@@ -468,36 +683,24 @@ public Builder setBaseName(final DocumentName baseName) {
}
/**
- * Sets the basename from a File. Sets {@link #root} and the {@link #baseName}
- * Will set the root.
- * @param file the file to set the base name from.
- * @return this.
+ * Executes the builder, sets the base name and clears the sameName flag.
+ * @param builder the builder for the base name.
*/
- public Builder setBaseName(final File file) {
- Pair pair = splitRoot(file);
- this.root = pair.getLeft();
- this.baseName = pair.getRight();
- return this;
+ private void setBaseName(final DocumentName.Builder builder) {
+ this.baseName = builder.build();
+ this.sameNameFlag = false;
}
/**
- * Sets the directory separator.
- * @param dirSeparator the directory separator to use.
- * @return this.
- */
- public Builder setDirSeparator(final String dirSeparator) {
- Objects.requireNonNull(dirSeparator, "Directory separator cannot be null");
- this.dirSeparator = dirSeparator;
- return this;
- }
-
- /**
- * Sets the {@link #isCaseSensitive} flag.
- * @param isCaseSensitive the expected state of the flag.
+ * Sets the basename from a File. Sets {@link #root} and the {@link #baseName}
+ * Will set the root.
+ * @param file the file to set the base name from.
* @return this.
*/
- public Builder setCaseSensitive(final boolean isCaseSensitive) {
- this.isCaseSensitive = isCaseSensitive;
+ public Builder setBaseName(final File file) {
+ DocumentName.Builder builder = DocumentName.builder(fsInfo).setName(file);
+ builder.sameNameFlag = true;
+ setBaseName(builder);
return this;
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java
index 80fe275e4..6b3c31bd0 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java
@@ -90,8 +90,8 @@ public DocumentNameMatcher(final String name, final MatchPatterns patterns, fina
/**
* Tokenizes name for faster Matcher processing.
- * @param name the name to tokenize
- * @param dirSeparator the directory separator
+ * @param name the name to tokenize.
+ * @param dirSeparator the directory separator.
* @return the tokenized name.
*/
private static char[][] tokenize(final String name, final String dirSeparator) {
@@ -316,12 +316,12 @@ public static DocumentNameMatcher and(final DocumentNameMatcher... matchers) {
}
/**
- * A DocumentName predicate that uses MatchPatterns.
+ * A DocumentName predicate that uses {@link MatchPatterns}.
*/
public static final class MatchPatternsPredicate implements Predicate {
- /** The base directory for the pattern matches */
+ /** The base directory for the pattern matches. */
private final DocumentName basedir;
- /** The pattern matchers */
+ /** The pattern matchers. */
private final MatchPatterns patterns;
private MatchPatternsPredicate(final DocumentName basedir, final MatchPatterns patterns) {
@@ -365,10 +365,10 @@ public String toString() {
}
/**
- * A DocumentName predicate that uses FileFilter.
+ * A DocumentName predicate that uses {@link FileFilter}.
*/
public static final class FileFilterPredicate implements Predicate {
- /** The file filter */
+ /** The file filter. */
private final FileFilter fileFilter;
private FileFilterPredicate(final FileFilter fileFilter) {
@@ -386,11 +386,15 @@ public String toString() {
}
}
+ /**
+ * A marker interface to indicate this predicate contains a collection of matchers.
+ */
interface CollectionPredicate extends Predicate {
Iterable getMatchers();
}
+
/**
- * A marker interface to indicate this predicate contains a collection of matchers.
+ * A marker class to indicate this predicate contains a collection of matchers.
*/
abstract static class CollectionPredicateImpl implements CollectionPredicate {
/** The collection for matchers that make up this predicate */
@@ -487,13 +491,13 @@ public boolean test(final DocumentName documentName) {
* Data from a {@link DocumentNameMatcher#decompose(DocumentName)} call.
*/
public static final class DecomposeData {
- /** The level this data was generated at */
+ /** The level this data was generated at. */
private final int level;
- /** The name of the DocumentNameMatcher that created this result */
+ /** The name of the DocumentNameMatcher that created this result. */
private final DocumentNameMatcher matcher;
/** The result of the check. */
private final boolean result;
- /** The candidate */
+ /** The actual candidate. */
private final DocumentName candidate;
private DecomposeData(final int level, final DocumentNameMatcher matcher, final DocumentName candidate, final boolean result) {
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/FileDocument.java b/apache-rat-core/src/main/java/org/apache/rat/document/FileDocument.java
index 3e7dec89b..d7596a3ef 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/FileDocument.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/FileDocument.java
@@ -42,20 +42,20 @@ public class FileDocument extends Document {
* Creates a File document.
* @param basedir the base directory for this document.
* @param file the file to wrap.
- * @param nameExcluder the path matcher to filter files/directories with.
+ * @param nameMatcher the path matcher to filter files/directories with.
*/
- public FileDocument(final DocumentName basedir, final File file, final DocumentNameMatcher nameExcluder) {
- super(DocumentName.builder(file).setBaseName(basedir.getBaseName()).build(), nameExcluder);
+ public FileDocument(final DocumentName basedir, final File file, final DocumentNameMatcher nameMatcher) {
+ super(DocumentName.builder(file).setBaseName(basedir.getBaseName()).build(), nameMatcher);
this.file = file;
}
/**
* Creates a File document where the baseDir is the root directory.
* @param file the file to wrap.
- * @param nameExcluder the path matcher to filter files/directories with.
+ * @param nameMatcher the path matcher to filter files/directories with.
*/
- public FileDocument(final File file, final DocumentNameMatcher nameExcluder) {
- super(DocumentName.builder(file).setBaseName(File.separator).build(), nameExcluder);
+ public FileDocument(final File file, final DocumentNameMatcher nameMatcher) {
+ super(DocumentName.builder(file).setBaseName(File.separator).build(), nameMatcher);
this.file = file;
}
@@ -70,12 +70,12 @@ public SortedSet listChildren() {
SortedSet result = new TreeSet<>();
File[] files = file.listFiles();
if (files != null) {
- FileFilter fileFilter = ExclusionUtils.asFileFilter(name, nameExcluder);
+ FileFilter fileFilter = ExclusionUtils.asFileFilter(name, nameMatcher);
for (File child : files) {
if (fileFilter.accept(child)) {
- result.add(new FileDocument(name, child, nameExcluder));
+ result.add(new FileDocument(name, child, nameMatcher));
} else {
- result.add(new IgnoredDocument(name, child, nameExcluder));
+ result.add(new IgnoredDocument(name, child, nameMatcher));
}
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java b/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java
index d9148701e..a50aa5ef8 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/walker/ArchiveWalker.java
@@ -35,6 +35,7 @@
import org.apache.rat.api.Document;
import org.apache.rat.api.RatException;
import org.apache.rat.document.ArchiveEntryDocument;
+import org.apache.rat.document.ArchiveEntryName;
import org.apache.rat.document.DocumentName;
import org.apache.rat.report.RatReport;
import org.apache.rat.utils.DefaultLog;
@@ -42,7 +43,7 @@
import static java.lang.String.format;
/**
- * Walks various kinds of archives files
+ * Walks various kinds of archives files.
*/
public class ArchiveWalker extends Walker {
@@ -68,7 +69,7 @@ public void run(final RatReport report) throws RatException {
}
/**
- * Creates an input stream from the Directory being walked.
+ * Creates an input stream from the directory being walked.
* @return A buffered input stream reading the archive data.
* @throws IOException on error
*/
@@ -83,19 +84,16 @@ private InputStream createInputStream() throws IOException {
public Collection getDocuments() throws RatException {
List result = new ArrayList<>();
try (ArchiveInputStream extends ArchiveEntry> input = new ArchiveStreamFactory().createArchiveInputStream(createInputStream())) {
- ArchiveEntry entry = null;
+ ArchiveEntry entry;
while ((entry = input.getNextEntry()) != null) {
if (!entry.isDirectory() && input.canReadEntryData(entry)) {
- DocumentName innerName = DocumentName.builder().setDirSeparator("/").setName(entry.getName())
- .setBaseName(".").setCaseSensitive(true).build();
- if (this.getDocument().getNameExcluder().matches(innerName)) {
+ DocumentName innerName = DocumentName.builder().setName(entry.getName())
+ .setBaseName(".").build();
+ if (this.getDocument().getNameMatcher().matches(innerName)) {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
IOUtils.copy(input, baos);
- DocumentName archiveName = getDocument().getName();
- String outerNameStr = format("%s#%s", archiveName.getName(), entry.getName());
- DocumentName outerName = DocumentName.builder(archiveName).setName(outerNameStr)
- .setCaseSensitive(true).build();
- result.add(new ArchiveEntryDocument(outerName, baos.toByteArray(), getDocument().getNameExcluder()));
+ ArchiveEntryName entryName = new ArchiveEntryName(getDocument().getName(), entry.getName());
+ result.add(new ArchiveEntryDocument(entryName, baos.toByteArray(), getDocument().getNameMatcher()));
}
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/walker/FileListWalker.java b/apache-rat-core/src/main/java/org/apache/rat/walker/FileListWalker.java
index 6e6c50e5a..056090858 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/walker/FileListWalker.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/walker/FileListWalker.java
@@ -25,6 +25,7 @@
import org.apache.commons.io.IOUtils;
import org.apache.rat.api.RatException;
import org.apache.rat.commandline.Arg;
+import org.apache.rat.config.exclusion.ExclusionUtils;
import org.apache.rat.document.DocumentName;
import org.apache.rat.document.DocumentNameMatcher;
import org.apache.rat.document.FileDocument;
@@ -37,12 +38,12 @@
* internally.
*/
public class FileListWalker implements IReportable {
- /** The source document name */
+ /** The source document name. */
private final FileDocument source;
- /** The root document name */
- private final FileDocument rootDoc;
- /** the base directory for the source document */
- private final FileDocument baseDoc;
+ /** The root document name. */
+ private final DocumentName rootDoc;
+ /** The base directory for the source document. */
+ private final DocumentName baseDoc;
/**
* Constructor.
@@ -51,22 +52,21 @@ public class FileListWalker implements IReportable {
public FileListWalker(final FileDocument source) {
this.source = source;
File baseDir = source.getFile().getParentFile().getAbsoluteFile();
- this.baseDoc = new FileDocument(baseDir, DocumentNameMatcher.MATCHES_ALL);
+ this.baseDoc = DocumentName.builder(baseDir).build();
File p = baseDir;
while (p.getParentFile() != null) {
p = p.getParentFile();
}
- File rootDir = p;
- rootDoc = new FileDocument(rootDir, DocumentNameMatcher.MATCHES_ALL);
+ this.rootDoc = DocumentName.builder(p).build();
}
private FileDocument createDocument(final String unixFileName) {
DocumentName sourceName = source.getName();
- String finalName = "/".equals(sourceName.getDirectorySeparator()) ? unixFileName :
- unixFileName.replace("/", sourceName.getDirectorySeparator());
- FileDocument documentBase = unixFileName.startsWith("/") ? rootDoc : baseDoc;
- File documentFile = new File(documentBase.getFile(), finalName);
- return new FileDocument(rootDoc.getName(), documentFile, DocumentNameMatcher.MATCHES_ALL);
+ String finalName = ExclusionUtils.convertSeparator(unixFileName, "/", sourceName.getDirectorySeparator());
+ DocumentName documentBase = unixFileName.startsWith("/") ? rootDoc : baseDoc;
+ DocumentName documentName = documentBase.resolve(finalName);
+ File documentFile = documentName.asFile();
+ return new FileDocument(documentBase, documentFile, DocumentNameMatcher.MATCHES_ALL);
}
@Override
diff --git a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
index f723e5fd1..c0d45c08a 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
@@ -25,6 +25,7 @@
import org.apache.commons.cli.ParseException;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.rat.commandline.ArgumentContext;
+import org.apache.rat.document.DocumentName;
import org.apache.rat.license.LicenseSetFactory;
import org.apache.rat.report.IReportable;
import org.apache.rat.test.AbstractOptionsProvider;
@@ -50,8 +51,8 @@
import java.util.concurrent.atomic.AtomicBoolean;
import static java.lang.String.format;
+
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;
public class OptionCollectionTest {
@@ -158,11 +159,12 @@ public void testDefaultConfiguration() throws ParseException {
@ParameterizedTest
@ValueSource(strings = { ".", "./", "target", "./target" })
public void getReportableTest(String fName) throws IOException {
- File expected = new File(fName);
+ File base = new File(fName);
+ String expected = DocumentName.FSInfo.getDefault().normalize(base.getAbsolutePath());
ReportConfiguration config = OptionCollection.parseCommands(testPath.toFile(), new String[]{fName}, o -> fail("Help called"), false);
- IReportable reportable = OptionCollection.getReportable(expected, config);
- assertNotNull(reportable, () -> format("'%s' returned null", fName));
- assertThat(reportable.getName().getName()).isEqualTo(expected.getAbsolutePath());
+ IReportable reportable = OptionCollection.getReportable(base, config);
+ assertThat(reportable).as(() -> format("'%s' returned null", fName)).isNotNull();
+ assertThat(reportable.getName().getName()).isEqualTo(expected);
}
/**
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 4e2461ce6..72ebff4be 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
@@ -114,8 +114,8 @@ public void archiveTypeAnalyserTest() throws Exception {
private static Stream archiveProcessingTestData() {
List lst = new ArrayList<>();
lst.add(Arguments.of(ReportConfiguration.Processing.NOTIFICATION, 0));
- lst.add(Arguments.of(ReportConfiguration.Processing.PRESENCE, 2));
- lst.add(Arguments.of(ReportConfiguration.Processing.ABSENCE, 3));
+ lst.add(Arguments.of(ReportConfiguration.Processing.PRESENCE, 1));
+ lst.add(Arguments.of(ReportConfiguration.Processing.ABSENCE, 2));
return lst.stream();
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java
index 580d10849..f8535a90b 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java
@@ -51,7 +51,13 @@ public void setup() {
}
private void testParseExclusion(DocumentNameMatcher nameMatcher, DocumentName name, boolean expected) {
- assertThat(nameMatcher.matches(name)).as(() -> format("Failed on [%s %s]", basedir, name)).isEqualTo(expected);
+ assertThat(nameMatcher.matches(name)).as(() -> format("Failed on [%s %s]%n%s", basedir, name, dump(nameMatcher, name))).isEqualTo(expected);
+ }
+
+ private String dump(DocumentNameMatcher nameMatcher, DocumentName name) {
+ StringBuilder sb = new StringBuilder();
+ nameMatcher.decompose(name).forEach(s -> sb.append(s).append("\n"));
+ return sb.toString();
}
private DocumentName mkName(String pth) {
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/FileProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/FileProcessorTest.java
index 0519cee82..922912674 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/FileProcessorTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/FileProcessorTest.java
@@ -22,6 +22,7 @@
import java.util.List;
import java.util.stream.Stream;
import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.FSInfoTest;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
@@ -40,7 +41,7 @@ void localizePatternTest(DocumentName baseName, String pattern, String expectedS
public static Stream localizePatternData() {
List lst = new ArrayList<>();
- DocumentName baseName = DocumentName.builder().setName("fileBeingRead").setBaseName("baseDir").setDirSeparator("/").build();
+ DocumentName baseName = DocumentName.builder(FSInfoTest.UNIX).setName("fileBeingRead").setBaseName("baseDir").build();
lst.add(Arguments.of(baseName, "file", "/baseDir/file"));
lst.add(Arguments.of(baseName, "!file", "!/baseDir/file"));
diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java
index def6ec447..beeeeca94 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameTest.java
@@ -19,39 +19,207 @@
package org.apache.rat.document;
import java.io.File;
+import java.io.FileFilter;
+import java.io.FilenameFilter;
+import java.io.IOException;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
import java.util.ArrayList;
+import java.util.Arrays;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import java.util.stream.Stream;
+
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang3.tuple.Pair;
+import org.apache.rat.config.exclusion.ExclusionUtils;
+import org.apache.rat.document.DocumentName.FSInfo;
+
import org.assertj.core.util.Files;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mockito;
-import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.apache.rat.document.FSInfoTest.OSX;
+import static org.apache.rat.document.FSInfoTest.UNIX;
+import static org.apache.rat.document.FSInfoTest.WINDOWS;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.mockito.ArgumentMatchers.any;
public class DocumentNameTest {
+ public static DocumentName mkName(Path tempDir, FSInfo fsInfo) {
+ File docFile = mkFile(tempDir.toFile(), fsInfo);
+ DocumentName result = DocumentName.builder(fsInfo).setName(docFile).build();
+ DocumentName mocked = Mockito.spy(result);
+
+ String fn = result.localized(FileSystems.getDefault().getSeparator());
+ File file = tempDir.resolve(fn.substring(1)).toFile();
+ File mockedFile = mkFile(file, fsInfo);
+ when(mocked.asFile()).thenReturn(mockedFile);
+
+ assertThat(mocked.asFile()).isEqualTo(mockedFile);
+ return mocked;
+ }
+
+ private static File[] listFiles(File file, FSInfo fsInfo) {
+ File[] fileList = file.listFiles();
+ if (fileList == null) {
+ return fileList;
+ }
+ return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).toArray(File[]::new);
+ }
+
+ private static File[] listFiles(File file, FSInfo fsInfo, FileFilter filter) {
+ File[] fileList = file.listFiles();
+ if (fileList == null) {
+ return fileList;
+ }
+ return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(filter::accept).toArray(File[]::new);
+ }
+
+ private static File[] listFiles(File file, FSInfo fsInfo, FilenameFilter filter) {
+ File[] fileList = file.listFiles();
+ if (fileList == null) {
+ return fileList;
+ }
+ return Arrays.stream(fileList).map(f -> mkFile(f, fsInfo)).filter(x -> filter.accept(x, x.getName())).toArray(File[]::new);
+ }
+
+ public static File mkFile(final File file, final FSInfo fsInfo) {
+ File mockedFile = mock(File.class);
+ when(mockedFile.listFiles()).thenAnswer( env -> listFiles(file, fsInfo));
+ when(mockedFile.listFiles(any(FilenameFilter.class))).thenAnswer( env -> listFiles(file, fsInfo, env.getArgument(0, FilenameFilter.class)));
+ when(mockedFile.listFiles(any(FileFilter.class))).thenAnswer(env -> listFiles(file, fsInfo, env.getArgument(0, FileFilter.class)));
+ when(mockedFile.getName()).thenReturn(ExclusionUtils.convertSeparator(file.getName(), FSInfoTest.DEFAULT.dirSeparator(), fsInfo.dirSeparator()));
+ when(mockedFile.getAbsolutePath()).thenReturn(ExclusionUtils.convertSeparator(file.getAbsolutePath(), FSInfoTest.DEFAULT.dirSeparator(), fsInfo.dirSeparator()));
+ when(mockedFile.isFile()).thenAnswer(env -> file.isFile());
+ when(mockedFile.exists()).thenAnswer(emv -> file.exists());
+ when(mockedFile.isDirectory()).thenAnswer(env -> file.isDirectory());
+
+ return mockedFile;
+ }
+
+ public static DocumentName mkName(Path tempDir, DocumentName baseDir, String pth) throws IOException {
+ DocumentName result = baseDir.resolve(ExclusionUtils.convertSeparator(pth, "/", baseDir.getDirectorySeparator()));
+ DocumentName mocked = Mockito.spy(result);
+
+ String fn = result.localized(FileSystems.getDefault().getSeparator());
+ File file = tempDir.resolve(fn.substring(1)).toFile();
+ File parent = file.getParentFile();
+ if (parent.exists() && !parent.isDirectory()) {
+ parent.delete();
+ }
+ parent.mkdirs();
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ FileUtils.deleteDirectory(file);
+ } else {
+ FileUtils.delete(file);
+ }
+ }
+ file.createNewFile();
+ when(mocked.asFile()).thenReturn(file);
+ return mocked;
+ }
+
+ @ParameterizedTest(name = "{index} {0} {2}")
+ @MethodSource("resolveTestData")
+ void resolveTest(String testName, DocumentName base, String toResolve, DocumentName expected) {
+ DocumentName actual = base.resolve(toResolve);
+ assertThat(actual).isEqualTo(expected);
+ }
+
+ private static Stream resolveTestData() {
+ List lst = new ArrayList<>();
+
+ DocumentName base = DocumentName.builder(UNIX).setName("/dir/unix").setBaseName("/").build();
+
+ DocumentName expected = DocumentName.builder(UNIX).setName("/dir/unix/relative").setBaseName("/").build();
+ lst.add(Arguments.of("unix", base, "relative", expected));
+
+ expected = DocumentName.builder(UNIX).setName("/from/root").setBaseName("/").build();
+ lst.add(Arguments.of("unix", base, "/from/root", expected));
+
+ expected = DocumentName.builder(UNIX).setName("dir/up/and/down").setBaseName("/").build();
+ lst.add(Arguments.of("unix", base, "../up/and/down", expected));
+
+ expected = DocumentName.builder(UNIX).setName("/from/root").setBaseName("/").build();
+ lst.add(Arguments.of("unix", base, "\\from\\root", expected));
+
+ expected = DocumentName.builder(UNIX).setName("dir/up/and/down").setBaseName("/").build();
+ lst.add(Arguments.of("unix", base, "..\\up\\and\\down", expected));
+
+ // WINDOWS
+ base = DocumentName.builder(WINDOWS).setName("\\dir\\windows").setBaseName("C:\\").build();
+
+ expected = DocumentName.builder(WINDOWS).setName("\\dir\\windows\\relative").setBaseName("C:\\").build();
+ lst.add(Arguments.of("windows", base, "relative", expected));
+
+ expected = DocumentName.builder(WINDOWS).setName("\\from\\root").setBaseName("C:\\").build();
+ lst.add(Arguments.of("windows", base, "/from/root", expected));
+
+ expected = DocumentName.builder(WINDOWS).setName("dir\\up\\and\\down").setBaseName("C:\\").build();
+ lst.add(Arguments.of("windows", base, "../up/and/down", expected));
+
+ expected = DocumentName.builder(WINDOWS).setName("\\from\\root").setBaseName("C:\\").build();
+ lst.add(Arguments.of("windows", base, "\\from\\root", expected));
+
+ expected = DocumentName.builder(WINDOWS).setName("dir\\up\\and\\down").setBaseName("C:\\").build();
+ lst.add(Arguments.of("windows", base, "..\\up\\and\\down", expected));
+
+ // OSX
+ base = DocumentName.builder(OSX).setName("/dir/osx").setBaseName("/").build();
+
+ expected = DocumentName.builder(OSX).setName("/dir/osx/relative").setBaseName("/").build();
+ lst.add(Arguments.of("osx", base, "relative", expected));
+
+ expected = DocumentName.builder(OSX).setName("/from/root").setBaseName("/").build();
+ lst.add(Arguments.of("osx", base, "/from/root", expected));
+
+ expected = DocumentName.builder(OSX).setName("dir/up/and/down").setBaseName("/").build();
+ lst.add(Arguments.of("osx", base, "../up/and/down", expected));
+
+ expected = DocumentName.builder(OSX).setName("/from/root").setBaseName("/").build();
+ lst.add(Arguments.of("osx", base, "\\from\\root", expected));
+
+ expected = DocumentName.builder(OSX).setName("dir/up/and/down").setBaseName("/").build();
+ lst.add(Arguments.of("osx", base, "..\\up\\and\\down", expected));
+
+ return lst.stream();
+ }
+
@Test
- public void localizeTest() {
- DocumentName documentName = DocumentName.builder().setName("/a/b/c")
- .setBaseName("/a").setDirSeparator("/").setCaseSensitive(false).build();
+ void localizeTest() {
+ DocumentName documentName = DocumentName.builder(UNIX).setName("/a/b/c")
+ .setBaseName("/a").build();
+ assertThat(documentName.localized()).isEqualTo("/b/c");
+ assertThat(documentName.localized("-")).isEqualTo("-b-c");
+
+ documentName = DocumentName.builder(WINDOWS).setName("\\a\\b\\c")
+ .setBaseName("\\a").build();
+ assertThat(documentName.localized()).isEqualTo("\\b\\c");
+ assertThat(documentName.localized("-")).isEqualTo("-b-c");
+
+ documentName = DocumentName.builder(OSX).setName("/a/b/c")
+ .setBaseName("/a").build();
assertThat(documentName.localized()).isEqualTo("/b/c");
assertThat(documentName.localized("-")).isEqualTo("-b-c");
}
- @ParameterizedTest(name ="{index} {0}")
+ @ParameterizedTest(name = "{index} {0}")
@MethodSource("validBuilderData")
void validBuilderTest(String testName, DocumentName.Builder builder, String root, String name, String baseName, String dirSeparator) {
DocumentName underTest = builder.build();
assertThat(underTest.getRoot()).as(testName).isEqualTo(root);
assertThat(underTest.getDirectorySeparator()).as(testName).isEqualTo(dirSeparator);
- assertThat(underTest.getName()).as(testName).isEqualTo(root+dirSeparator+name);
- assertThat(underTest.getBaseName()).as(testName).isEqualTo(root+dirSeparator+baseName);
+ assertThat(underTest.getName()).as(testName).isEqualTo(root + dirSeparator + name);
+ assertThat(underTest.getBaseName()).as(testName).isEqualTo(root + dirSeparator + baseName);
}
private static Stream validBuilderData() {
@@ -94,98 +262,65 @@ private static Stream validBuilderData() {
lst.add(Arguments.of("setName(root)", DocumentName.builder().setName(r), root, "", "", File.separator));
lst.add(Arguments.of("Builder(root)", DocumentName.builder(r), root, "", "", File.separator));
- lst.add(Arguments.of("foo/bar foo", DocumentName.builder().setDirSeparator("/")
+
+ lst.add(Arguments.of("foo/bar foo", DocumentName.builder(UNIX)
.setName("/foo/bar").setBaseName("foo"), "", "foo/bar", "foo", "/"));
- DocumentName.Builder builder = DocumentName.builder().setDirSeparator("\\").setName("\\foo\\bar").setBaseName("foo")
+
+ DocumentName.Builder builder = DocumentName.builder(WINDOWS).setName("\\foo\\bar").setBaseName("C:\\foo")
.setRoot("C:");
- lst.add(Arguments.of("C:\\foo\\bar foo", builder, "C:", "foo\\bar", "foo", "\\"));
+ lst.add(Arguments.of("\\foo\\bar foo", builder, "C:", "foo\\bar", "foo", "\\"));
+
+ lst.add(Arguments.of("foo/bar foo", DocumentName.builder(OSX)
+ .setName("/foo/bar").setBaseName("foo"), "", "foo/bar", "foo", "/"));
return lst.stream();
}
@Test
- public void splitRootsTest() {
- Set preserve = new HashSet<>(DocumentName.ROOTS);
- try {
- DocumentName.ROOTS.clear();
- DocumentName.ROOTS.add("C:\\");
- Pair result = DocumentName.Builder.splitRoot("C:\\My\\path\\to\\a\\file.txt", "\\");
- assertThat(result.getLeft()).isEqualTo("C:");
- assertThat(result.getRight()).isEqualTo("My\\path\\to\\a\\file.txt");
-
-
- DocumentName.ROOTS.clear();
- DocumentName.ROOTS.add("/");
- result = DocumentName.Builder.splitRoot("/My/path/to/a/file.txt", "/");
- assertThat(result.getLeft()).isEqualTo("");
- assertThat(result.getRight()).isEqualTo("My/path/to/a/file.txt");
-
- } finally {
- DocumentName.ROOTS.clear();
- DocumentName.ROOTS.addAll(preserve);
- }
+ void splitRootsTest() {
+ Pair result = DocumentName.builder(WINDOWS).splitRoot("C:\\My\\path\\to\\a\\file.txt");
+ assertThat(result.getLeft()).isEqualTo("C:");
+ assertThat(result.getRight()).isEqualTo("My\\path\\to\\a\\file.txt");
+
+ result = DocumentName.builder(UNIX).splitRoot("/My/path/to/a/file.txt");
+ assertThat(result.getLeft()).isEqualTo("");
+ assertThat(result.getRight()).isEqualTo("My/path/to/a/file.txt");
+
+ result = DocumentName.builder(OSX).splitRoot("/My/path/to/a/file.txt");
+ assertThat(result.getLeft()).isEqualTo("");
+ assertThat(result.getRight()).isEqualTo("My/path/to/a/file.txt");
}
@Test
- public void archiveEntryNameTest() {
- Set preserve = new HashSet<>(DocumentName.ROOTS);
- try {
- DocumentName.ROOTS.clear();
- DocumentName.ROOTS.add("C:\\");
-
- DocumentName archiveName = DocumentName.builder().setDirSeparator("\\")
- .setName("C:\\archives\\anArchive.zip").setBaseName("archives").build();
- assertThat(archiveName.getRoot()).isEqualTo("C:");
- assertThat(archiveName.getDirectorySeparator()).isEqualTo("\\");
- assertThat(archiveName.getBaseName()).isEqualTo("C:\\archives");
- assertThat(archiveName.getName()).isEqualTo("C:\\archives\\anArchive.zip");
- assertThat(archiveName.localized()).isEqualTo("\\anArchive.zip");
-
- String entryName = "./anArchiveEntry.txt";
- DocumentName innerName = DocumentName.builder()
- .setDirSeparator("/").setName(entryName)
- .setBaseName(".").setCaseSensitive(true).build();
- assertThat(innerName.getRoot()).isEqualTo("");
- assertThat(innerName.getDirectorySeparator()).isEqualTo("/");
- assertThat(innerName.getBaseName()).isEqualTo("/.");
- assertThat(innerName.getName()).isEqualTo("/" + entryName);
- assertThat(innerName.localized()).isEqualTo("/anArchiveEntry.txt");
-
- String outerNameStr = format("%s#%s", archiveName.getName(), entryName);
- DocumentName outerName = DocumentName.builder(archiveName).setName(outerNameStr)
- .setCaseSensitive(innerName.isCaseSensitive()).build();
-
- assertThat(outerName.getRoot()).isEqualTo("C:");
- assertThat(outerName.getDirectorySeparator()).isEqualTo("\\");
- assertThat(outerName.getBaseName()).isEqualTo("C:\\archives");
- assertThat(outerName.getName()).isEqualTo("C:\\archives\\anArchive.zip#./anArchiveEntry.txt");
- assertThat(outerName.localized()).isEqualTo("\\anArchive.zip#./anArchiveEntry.txt");
- assertThat(outerName.localized("/")).isEqualTo("/anArchive.zip#./anArchiveEntry.txt");
-
- // test with directory
- entryName = "./someDir/anArchiveEntry.txt";
- innerName = DocumentName.builder()
- .setDirSeparator("/").setName(entryName)
- .setBaseName(".").setCaseSensitive(true).build();
- assertThat(innerName.getRoot()).isEqualTo("");
- assertThat(innerName.getDirectorySeparator()).isEqualTo("/");
- assertThat(innerName.getBaseName()).isEqualTo("/.");
- assertThat(innerName.getName()).isEqualTo("/" + entryName);
- assertThat(innerName.localized()).isEqualTo("/someDir/anArchiveEntry.txt");
-
- outerNameStr = format("%s#%s", archiveName.getName(), entryName);
- outerName = DocumentName.builder(archiveName).setName(outerNameStr)
- .setCaseSensitive(innerName.isCaseSensitive()).build();
-
- assertThat(outerName.getRoot()).isEqualTo("C:");
- assertThat(outerName.getDirectorySeparator()).isEqualTo("\\");
- assertThat(outerName.getBaseName()).isEqualTo("C:\\archives");
- assertThat(outerName.getName()).isEqualTo("C:\\archives\\anArchive.zip#./someDir/anArchiveEntry.txt");
- assertThat(outerName.localized()).isEqualTo("\\anArchive.zip#./someDir/anArchiveEntry.txt");
- assertThat(outerName.localized("/")).isEqualTo("/anArchive.zip#./someDir/anArchiveEntry.txt");
- } finally {
- DocumentName.ROOTS.clear();
- DocumentName.ROOTS.addAll(preserve);
- }
+ void archiveEntryNameTest() {
+ String entryName = "./anArchiveEntry.txt";
+ DocumentName archiveName = DocumentName.builder(WINDOWS)
+ .setName("C:\\archives\\anArchive.zip").setBaseName("C:\\archives").build();
+
+ assertThat(archiveName.getRoot()).isEqualTo("C:");
+ assertThat(archiveName.getDirectorySeparator()).isEqualTo("\\");
+ assertThat(archiveName.getBaseName()).isEqualTo("C:\\archives");
+ assertThat(archiveName.getName()).isEqualTo("C:\\archives\\anArchive.zip");
+ assertThat(archiveName.localized()).isEqualTo("\\anArchive.zip");
+
+ ArchiveEntryName archiveEntryName = new ArchiveEntryName(archiveName, entryName);
+
+ assertThat(archiveEntryName.getRoot()).isEqualTo(archiveName.getName()+"#");
+ assertThat(archiveEntryName.getDirectorySeparator()).isEqualTo("/");
+ assertThat(archiveEntryName.getBaseName()).isEqualTo("C:\\archives\\anArchive.zip#");
+ assertThat(archiveEntryName.getName()).isEqualTo("C:\\archives\\anArchive.zip#/anArchiveEntry.txt");
+ assertThat(archiveEntryName.localized()).isEqualTo("/anArchiveEntry.txt");
+ assertThat(archiveEntryName.localized("/")).isEqualTo("/anArchive.zip#/anArchiveEntry.txt");
+
+ // test with directory
+ entryName = "./someDir/anArchiveEntry.txt";
+ archiveEntryName = new ArchiveEntryName(archiveName, entryName);
+
+ assertThat(archiveEntryName.getRoot()).isEqualTo(archiveName.getName()+"#");
+ assertThat(archiveEntryName.getDirectorySeparator()).isEqualTo("/");
+ assertThat(archiveEntryName.getBaseName()).isEqualTo("C:\\archives\\anArchive.zip#");
+ assertThat(archiveEntryName.getName()).isEqualTo("C:\\archives\\anArchive.zip#/someDir/anArchiveEntry.txt");
+ assertThat(archiveEntryName.localized()).isEqualTo("/someDir/anArchiveEntry.txt");
+ assertThat(archiveEntryName.localized("/")).isEqualTo("/anArchive.zip#/someDir/anArchiveEntry.txt");
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/FSInfoTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/FSInfoTest.java
new file mode 100644
index 000000000..ced9d8c62
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/document/FSInfoTest.java
@@ -0,0 +1,58 @@
+/*
+ * 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.document;
+
+import com.google.common.jimfs.Configuration;
+import com.google.common.jimfs.Jimfs;
+import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
+import java.util.Arrays;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.provider.Arguments;
+
+public class FSInfoTest {
+ public static final DocumentName.FSInfo DEFAULT;
+ public static final DocumentName.FSInfo OSX;
+ public static final DocumentName.FSInfo UNIX;
+ public static final DocumentName.FSInfo WINDOWS;
+
+ static {
+ try (FileSystem osx = Jimfs.newFileSystem(Configuration.osX());
+ FileSystem unix = Jimfs.newFileSystem(Configuration.unix());
+ FileSystem windows = Jimfs.newFileSystem(Configuration.windows())) {
+ OSX = new DocumentName.FSInfo("osx", osx);
+ UNIX = new DocumentName.FSInfo("unix", unix);
+ WINDOWS = new DocumentName.FSInfo("windows", windows);
+ DEFAULT = new DocumentName.FSInfo("default", FileSystems.getDefault());
+ } catch (IOException e) {
+ throw new RuntimeException("Unable to creat FSInfo objects: " + e.getMessage(), e);
+ }
+ }
+
+ public static final DocumentName.FSInfo[] TEST_SUITE = {UNIX, WINDOWS, OSX};
+
+ /**
+ * Provides arguments for parameterized tests that only require the fsInfo.
+ * @return a stream of TEST_SUITE based Arguments.
+ */
+ public static Stream fsInfoArgs() {
+ return Arrays.stream(TEST_SUITE).map(Arguments::of);
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java
index 2abf19340..87d157a0e 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java
@@ -22,6 +22,7 @@
import java.util.List;
import java.util.stream.Stream;
import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.FSInfoTest;
import org.apache.rat.testhelpers.TestingDocument;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
@@ -41,10 +42,8 @@ public void testMatches(DocumentName testingName, boolean expected) {
private static Stream nameData() {
List lst = new ArrayList<>();
- final DocumentName linuxBaseName = DocumentName.builder().setName("/").setBaseName("/").setDirSeparator("/")
- .setCaseSensitive(true).build();
- final DocumentName windowsBaseName = DocumentName.builder().setName("\\").setBaseName("\\")
- .setDirSeparator("\\").setCaseSensitive(false).build();
+ final DocumentName linuxBaseName = DocumentName.builder(FSInfoTest.UNIX).setName("/").setBaseName("/").build();
+ final DocumentName windowsBaseName = DocumentName.builder(FSInfoTest.WINDOWS).setName("\\").setBaseName("\\").build();
lst.add(Arguments.of(linuxBaseName.resolve("DEPENDENCIES"), true));
lst.add(Arguments.of(linuxBaseName.resolve("LICENSE"), true));
diff --git a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java
index 57c5a0518..8a34245e9 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java
@@ -244,7 +244,7 @@ protected DocumentName mkDocName(String name) {
return DocumentName.builder(new File(baseDir, name)).build();
}
- /* tests to be implemented */
+ /* Tests to be implemented */
protected abstract void helpTest();
/* Display the option and value under test */
@@ -344,6 +344,12 @@ protected void inputExcludeParsedScmTest() {
try {
ReportConfiguration config = generateConfig(ImmutablePair.of(option, args));
DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
+ for (String fname : notExcluded) {
+ final DocumentName docName = mkDocName(fname);
+ assertThat(excluder.matches(docName))
+ .as(() -> String.format("option: %s name: %s%n%s", option.getKey(), fname, excluder.decompose(docName)))
+ .isTrue();
+ }
for (String fname : excluded) {
DocumentName docName = mkDocName(fname);
assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
@@ -392,6 +398,12 @@ private void execIncludeTest(Option option, String[] args) {
ReportConfiguration config = generateConfig(ImmutablePair.of(option, args),
ImmutablePair.of(excludeOption, EXCLUDE_ARGS));
DocumentNameMatcher excluder = config.getDocumentExcluder(baseName());
+ for (String fname : notExcluded) {
+ final DocumentName docName = mkDocName(fname);
+ assertThat(excluder.matches(docName))
+ .as(() -> String.format("option: %s name: %s%n%s", option.getKey(), fname, excluder.decompose(docName)))
+ .isTrue();
+ }
for (String fname : excluded) {
DocumentName docName = mkDocName(fname);
assertThat(excluder.matches(docName)).as(() -> dump(option, fname, excluder, docName)).isFalse();
diff --git a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java
index c1e756687..1bd66377b 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/testhelpers/TestingDocument.java
@@ -29,6 +29,7 @@
import org.apache.rat.api.Document;
import org.apache.rat.document.DocumentNameMatcher;
import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.FSInfoTest;
public class TestingDocument extends Document {
@@ -50,19 +51,19 @@ public TestingDocument(DocumentName documentName) {
}
public TestingDocument(String name, DocumentNameMatcher matcher) {
- super(DocumentName.builder().setName(name).setBaseName("").setDirSeparator("/").setCaseSensitive(true).build(), matcher);
+ super(DocumentName.builder().setName(name).setBaseName("").build(), matcher);
this.reader = null;
this.input = null;
}
public TestingDocument(Reader reader, String name) {
- super(DocumentName.builder().setName(name).setBaseName("").setDirSeparator("/").setCaseSensitive(true).build(), DocumentNameMatcher.MATCHES_ALL);
+ super(DocumentName.builder().setName(name).setBaseName("").build(), DocumentNameMatcher.MATCHES_ALL);
this.reader = reader;
this.input = null;
}
public TestingDocument(IOSupplier inputStream, String name) {
- super(DocumentName.builder().setName(name).setBaseName("").setDirSeparator("/").setCaseSensitive(true).build(), DocumentNameMatcher.MATCHES_ALL);
+ super(DocumentName.builder(FSInfoTest.UNIX).setName(name).setBaseName("").build(), DocumentNameMatcher.MATCHES_ALL);
this.input = inputStream;
this.reader = null;
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/walker/FileListWalkerTest.java b/apache-rat-core/src/test/java/org/apache/rat/walker/FileListWalkerTest.java
index 14ac1478b..ec739f643 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/walker/FileListWalkerTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/walker/FileListWalkerTest.java
@@ -33,8 +33,7 @@
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.assertj.core.api.Assertions.assertThat;
public class FileListWalkerTest {
@@ -84,7 +83,7 @@ public static void setUp() throws Exception {
source = new File(working, "source.txt");
- DocumentName sourceName = DocumentName.builder(source).setBaseName(working.getAbsolutePath()).build();
+ DocumentName sourceName = DocumentName.builder(source).build();
File regular = new File(working, "regular");
regular.mkdir();
fileWriter(regular, "regularFile", "regular file");
@@ -111,8 +110,6 @@ public static void setUp() throws Exception {
writer.flush();
System.out.flush();
}
-
- hiddenName = DocumentName.builder(hiddenFile).setBaseName(rootName.getBaseName()).build();
}
@Test
@@ -122,10 +119,7 @@ public void readFilesTest() throws RatException {
walker.run(new TestRatReport(scanned));
String[] expected = {regularName.localized("/"), hiddenName.localized("/"),
anotherName.localized("/")};
- assertEquals(3, scanned.size());
- for (String ex : expected) {
- assertTrue(scanned.contains(ex), ()-> String.format("Missing %s from %s", ex, String.join(", ", scanned)));
- }
+ assertThat(scanned).containsExactly(expected);
}
static class TestRatReport implements RatReport {
diff --git a/pom.xml b/pom.xml
index 7bfceb031..4d164ecba 100644
--- a/pom.xml
+++ b/pom.xml
@@ -217,6 +217,12 @@ agnostic home for software distribution comprehension and audit tools.
2.4.21test
+
+ com.google.jimfs
+ jimfs
+ 1.3.0
+ test
+
@@ -379,8 +385,8 @@ agnostic home for software distribution comprehension and audit tools.
spotbugs-maven-plugin4.8.6.6
-
- 94
+
+ 98trueorg.apache.rat.-
@@ -489,7 +495,7 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.pluginsmaven-remote-resources-plugin
- 3.3.0
+ 3.2.0org.apache.maven.plugins
From e26e24d2750d272c14f2660b4799109df0b57ba3 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Tue, 28 Jan 2025 00:24:12 +0000
Subject: [PATCH 26/41] Bump
org.apache.maven.plugins:maven-remote-resources-plugin
Bumps [org.apache.maven.plugins:maven-remote-resources-plugin](https://github.com/apache/maven-remote-resources-plugin) from 3.2.0 to 3.3.0.
- [Release notes](https://github.com/apache/maven-remote-resources-plugin/releases)
- [Commits](https://github.com/apache/maven-remote-resources-plugin/compare/maven-remote-resources-plugin-3.2.0...maven-remote-resources-plugin-3.3.0)
---
updated-dependencies:
- dependency-name: org.apache.maven.plugins:maven-remote-resources-plugin
dependency-type: direct:production
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
---
pom.xml | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/pom.xml b/pom.xml
index 4d164ecba..bc593b4e8 100644
--- a/pom.xml
+++ b/pom.xml
@@ -495,7 +495,7 @@ agnostic home for software distribution comprehension and audit tools.
org.apache.maven.pluginsmaven-remote-resources-plugin
- 3.2.0
+ 3.3.0org.apache.maven.plugins
From c5a31fecc3b6d3697e20cb867e82c55decf969be Mon Sep 17 00:00:00 2001
From: "P. Ottlinger"
Date: Fri, 31 Jan 2025 13:25:55 +0100
Subject: [PATCH 27/41] RAT-379: Add changelog about bugfix in Eclipse
---
src/changes/changes.xml | 3 +++
1 file changed, 3 insertions(+)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 186d9c9b9..6805f0069 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -75,6 +75,9 @@ The type attribute can be one of:
Integrate Creadur RAT into the updated develocity.apache.org instance.
+
+ Fix 'Path must include project or resource name: /' error after importing RAT into Eclipse IDE by changing the way resources are copied around submodules.
+
Verify that projects that configure valid other licenses than the defaults, report correctly as well.
From ac0ebf3cc86d2a8d240d89b8053214ae13ec5b9b Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Tue, 4 Feb 2025 01:26:41 +0100
Subject: [PATCH 28/41] RAT-98: fixed DocumentNameMatcher idiom misuse (#435)
* fixed DocumentNameMatcher idiom misuse
* fixed chekstyle issue
---
.../rat/document/DocumentNameMatcher.java | 33 ++++++-------------
1 file changed, 10 insertions(+), 23 deletions(-)
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java
index 6b3c31bd0..5082c1a27 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentNameMatcher.java
@@ -23,7 +23,6 @@
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Collection;
-import java.util.Iterator;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Optional;
@@ -303,7 +302,16 @@ public static DocumentNameMatcher matcherSet(final DocumentNameMatcher includes,
return MATCHES_ALL;
}
List workingSet = Arrays.asList(includes, excludes);
- return new DocumentNameMatcher(format("matcherSet(%s)", join(workingSet)), new MatcherPredicate(workingSet));
+ return new DocumentNameMatcher(format("matcherSet(%s)", join(workingSet)),
+ new CollectionPredicateImpl(workingSet) {
+ @Override
+ public boolean test(final DocumentName documentName) {
+ if (includes.matches(documentName)) {
+ return true;
+ }
+ return !excludes.matches(documentName);
+ }
+ });
}
/**
@@ -466,27 +474,6 @@ public boolean test(final DocumentName documentName) {
}
}
- /**
- * An implementation of "or" logic across a collection of DocumentNameMatchers.
- */
- // package private for testing access
- static class MatcherPredicate extends CollectionPredicateImpl {
- MatcherPredicate(final Iterable matchers) {
- super(matchers);
- }
-
- @Override
- public boolean test(final DocumentName documentName) {
- Iterator iter = getMatchers().iterator();
- // included
- if (iter.next().matches(documentName)) {
- return true;
- }
- // excluded
- return !iter.next().matches(documentName);
- }
- }
-
/**
* Data from a {@link DocumentNameMatcher#decompose(DocumentName)} call.
*/
From 34dcb05db326374b19ddb3d864cf60656d41bae4 Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Tue, 4 Feb 2025 01:28:37 +0100
Subject: [PATCH 29/41] RAT-98: Add file arg converter (#425)
* added working directory
* updated merge issues
* Added FSInfo to handle file system differences
* updated spotbugs
* attempt to fix windows error
* fixed merge error
* fixed pattern match
* fix for file delete on windows
* added more descriptive failure messages
* added file converter + test
* fixes file list walker
* Prevent possible NPE
* Minor review changes
---------
Co-authored-by: P. Ottlinger
---
.../java/org/apache/rat/commandline/Arg.java | 38 +++++++------
.../apache/rat/commandline/Converters.java | 57 +++++++++++++++++--
.../config/exclusion/plexus/MatchPattern.java | 3 +-
.../exclusion/plexus/MatchPatterns.java | 5 +-
.../org/apache/rat/commandline/ArgTests.java | 16 +++---
.../org/apache/rat/mp/AbstractRatMojo.java | 8 +--
.../apache/rat/anttasks/ReportOptionTest.java | 2 +-
7 files changed, 91 insertions(+), 38 deletions(-)
diff --git a/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java b/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java
index 3ba85b95a..c14607c51 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/commandline/Arg.java
@@ -119,10 +119,14 @@ public enum Arg {
CONFIGURATION(new OptionGroup()
.addOption(Option.builder().longOpt("config").hasArgs().argName("File")
.desc("File names for system configuration.")
+ .converter(Converters.FILE_CONVERTER)
+ .type(File.class)
.build())
.addOption(Option.builder().longOpt("licenses").hasArgs().argName("File")
.desc("File names for system configuration.")
.deprecated(DeprecatedAttributes.builder().setSince("0.17").setForRemoval(true).setDescription(StdMsgs.useMsg("--config")).get())
+ .converter(Converters.FILE_CONVERTER)
+ .type(File.class)
.build())),
/**
@@ -186,7 +190,6 @@ public enum Arg {
.hasArg().argName("File").type(File.class)
.converter(Converters.FILE_CONVERTER)
.desc("Name of file containing the denied license IDs.")
- .converter(Converters.FILE_CONVERTER)
.build())),
/**
@@ -234,6 +237,7 @@ public enum Arg {
"File names must use linux directory separator ('/') or none at all. " +
"File names that do not start with '/' are relative to the directory where the " +
"argument is located.")
+ .converter(Converters.FILE_CONVERTER)
.type(File.class)
.build())),
@@ -585,8 +589,9 @@ private static void processConfigurationArgs(final ArgumentContext context) thro
try {
Defaults.Builder defaultBuilder = Defaults.builder();
if (CONFIGURATION.isSelected()) {
- for (String fn : context.getCommandLine().getOptionValues(CONFIGURATION.getSelected())) {
- defaultBuilder.add(fn);
+ File[] files = CONFIGURATION.getParsedOptionValues(context.getCommandLine());
+ for (File file : files) {
+ defaultBuilder.add(file);
}
}
if (CONFIGURATION_NO_DEFAULTS.isSelected()) {
@@ -607,7 +612,7 @@ private static void processConfigurationArgs(final ArgumentContext context) thro
try (InputStream in = Files.newInputStream(f.toPath())) {
context.getConfiguration().addApprovedLicenseCategories(IOUtils.readLines(in, StandardCharsets.UTF_8));
}
- } catch (IOException | ParseException e) {
+ } catch (IOException e) {
throw new ConfigurationException(e);
}
}
@@ -622,7 +627,7 @@ private static void processConfigurationArgs(final ArgumentContext context) thro
try (InputStream in = Files.newInputStream(f.toPath())) {
context.getConfiguration().removeApprovedLicenseCategories(IOUtils.readLines(in, StandardCharsets.UTF_8));
}
- } catch (IOException | ParseException e) {
+ } catch (IOException e) {
throw new ConfigurationException(e);
}
}
@@ -634,11 +639,11 @@ private static void processConfigurationArgs(final ArgumentContext context) thro
}
if (LICENSES_APPROVED_FILE.isSelected()) {
try {
- File f = context.getCommandLine().getParsedOptionValue(LICENSES_APPROVED_FILE.getSelected());
- try (InputStream in = Files.newInputStream(f.toPath())) {
+ File file = context.getCommandLine().getParsedOptionValue(LICENSES_APPROVED_FILE.getSelected());
+ try (InputStream in = Files.newInputStream(file.toPath())) {
context.getConfiguration().addApprovedLicenseIds(IOUtils.readLines(in, StandardCharsets.UTF_8));
}
- } catch (IOException | ParseException e) {
+ } catch (IOException e) {
throw new ConfigurationException(e);
}
}
@@ -649,11 +654,11 @@ private static void processConfigurationArgs(final ArgumentContext context) thro
}
if (LICENSES_DENIED_FILE.isSelected()) {
try {
- File f = context.getCommandLine().getParsedOptionValue(LICENSES_DENIED_FILE.getSelected());
- try (InputStream in = Files.newInputStream(f.toPath())) {
+ File file = context.getCommandLine().getParsedOptionValue(LICENSES_DENIED_FILE.getSelected());
+ try (InputStream in = Files.newInputStream(file.toPath())) {
context.getConfiguration().removeApprovedLicenseIds(IOUtils.readLines(in, StandardCharsets.UTF_8));
}
- } catch (IOException | ParseException e) {
+ } catch (IOException e) {
throw new ConfigurationException(e);
}
}
@@ -795,6 +800,7 @@ public static void processLogLevel(final CommandLine commandLine) {
* @throws ConfigurationException on error
*/
public static void processArgs(final ArgumentContext context) throws ConfigurationException {
+ Converters.FILE_CONVERTER.setWorkingDirectory(context.getWorkingDirectory());
processOutputArgs(context);
processEditArgs(context);
processInputArgs(context);
@@ -843,12 +849,12 @@ private static void processOutputArgs(final ArgumentContext context) {
if (OUTPUT_FILE.isSelected()) {
try {
- File f = context.getCommandLine().getParsedOptionValue(OUTPUT_FILE.getSelected());
- File parent = f.getParentFile();
+ File file = context.getCommandLine().getParsedOptionValue(OUTPUT_FILE.getSelected());
+ File parent = file.getParentFile();
if (!parent.mkdirs() && !parent.isDirectory()) {
- DefaultLog.getInstance().error("Could not create report parent directory " + f);
+ DefaultLog.getInstance().error("Could not create report parent directory " + file);
}
- context.getConfiguration().setOut(f);
+ context.getConfiguration().setOut(file);
} catch (ParseException e) {
context.logParseException(e, OUTPUT_FILE.getSelected(), "System.out");
context.getConfiguration().setOut((IOSupplier) null);
@@ -857,7 +863,7 @@ private static void processOutputArgs(final ArgumentContext context) {
if (OUTPUT_STYLE.isSelected()) {
String selected = OUTPUT_STYLE.getSelected().getKey();
- if (selected.equals("x")) {
+ if ("x".equals(selected)) {
// display deprecated message.
context.getCommandLine().hasOption("x");
context.getConfiguration().setStyleSheet(StyleSheets.getStyleSheet("xml"));
diff --git a/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java b/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java
index 197703f93..78333e599 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/commandline/Converters.java
@@ -19,16 +19,18 @@
package org.apache.rat.commandline;
import java.io.File;
+import java.io.IOException;
import org.apache.commons.cli.Converter;
import org.apache.commons.lang3.tuple.Pair;
import org.apache.rat.ConfigurationException;
+import org.apache.rat.document.DocumentName;
import org.apache.rat.report.claim.ClaimStatistic;
import static java.lang.String.format;
/**
- * Customized converters for Arg processing
+ * Customized converters for Arg processing.
*/
public final class Converters {
@@ -37,11 +39,12 @@ private Converters() {
}
/**
- * Creates a File with fully qualified name
+ * Creates a File with fully qualified name.
*/
- public static final Converter FILE_CONVERTER = s -> new File(s).getAbsoluteFile();
+ public static final FileConverter FILE_CONVERTER = new FileConverter();
+
/**
- * converts the Converter pattern into a Converter, count pair.
+ * Converts the Converter pattern into a Converter, count pair.
*/
public static final Converter, ConfigurationException> COUNTER_CONVERTER = arg -> {
String[] parts = arg.split(":");
@@ -55,4 +58,50 @@ private Converters() {
throw new ConfigurationException(format("'%s' is not a valid Counter", parts[0]), e);
}
};
+
+ /**
+ * A converter that can handle relative or absolute files.
+ */
+ public static final class FileConverter implements Converter {
+ /** The working directory to resolve relative files against. */
+ private DocumentName workingDirectory;
+
+ /**
+ * The constructor.
+ */
+ private FileConverter() {
+ // private construction only.
+ }
+
+ /**
+ * Sets the working directory for the conversion.
+ * @param workingDirectory current working directory
+ */
+ public void setWorkingDirectory(final DocumentName workingDirectory) {
+ this.workingDirectory = workingDirectory;
+ }
+
+ /**
+ * Applies the conversion function to the specified file name.
+ * @param fileName the file name to create a file from.
+ * @return a File.
+ * @throws NullPointerException if {@code fileName} is null.
+ */
+ public File apply(final String fileName) throws NullPointerException {
+ File file = new File(fileName);
+ // is this a relative file?
+ if (!fileName.startsWith(File.separator)) {
+ // check for a root provided (e.g. C:\\)"
+ if (!DocumentName.FSInfo.getDefault().rootFor(fileName).isPresent()) {
+ // no root, resolve against workingDirectory
+ file = new File(workingDirectory.resolve(fileName).getName()).getAbsoluteFile();
+ }
+ }
+ try {
+ return file.getCanonicalFile();
+ } catch (IOException e) {
+ return file.getAbsoluteFile();
+ }
+ }
+ }
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPattern.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPattern.java
index 9932376ff..11b71445d 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPattern.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPattern.java
@@ -117,8 +117,7 @@ public boolean startsWith(final String string) {
@Override
public String toString() {
- return Arrays.asList(tokenized)
- .toString();
+ return Arrays.asList(tokenized).toString();
}
public String source() {
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPatterns.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPatterns.java
index 0a6703934..06c4672d6 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPatterns.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/MatchPatterns.java
@@ -42,10 +42,7 @@ private MatchPatterns(final MatchPattern[] patterns) {
@Override
public String toString() {
- return Arrays.stream(patterns)
- .map(MatchPattern::toString)
- .collect(Collectors.toList())
- .toString();
+ return Arrays.stream(patterns).map(MatchPattern::toString).collect(Collectors.toList()).toString();
}
public String source() {
diff --git a/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java b/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java
index 7472a0a9e..7f27cb8d1 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/commandline/ArgTests.java
@@ -18,6 +18,7 @@
*/
package org.apache.rat.commandline;
+import java.io.IOException;
import org.apache.commons.cli.CommandLine;
import org.apache.commons.cli.DefaultParser;
import org.apache.commons.cli.Options;
@@ -25,12 +26,13 @@
import org.apache.rat.DeprecationReporter;
import org.apache.rat.OptionCollection;
import org.apache.rat.ReportConfiguration;
+import org.apache.rat.document.DocumentName;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.ValueSource;
import java.io.File;
-import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.assertj.core.api.Assertions.assertThat;
public class ArgTests {
@@ -40,9 +42,9 @@ private CommandLine createCommandLine(String[] args) throws ParseException {
.setAllowPartialMatching(true).build().parse(opts, args);
}
- @ParameterizedTest
+ @ParameterizedTest(name = "{0}")
@ValueSource(strings = { "rat.txt", "./rat.txt", "/rat.txt", "target/rat.test" })
- public void outputFleNameNoDirectoryTest(String name) throws ParseException {
+ public void outputFleNameNoDirectoryTest(String name) throws ParseException, IOException {
class OutputFileConfig extends ReportConfiguration {
private File actual = null;
@Override
@@ -50,13 +52,13 @@ public void setOut(File file) {
actual = file;
}
}
+ String fileName = name.replace("/", DocumentName.FSInfo.getDefault().dirSeparator());
+ File expected = new File(fileName);
- File expected = new File(name);
-
- CommandLine commandLine = createCommandLine(new String[] {"--output-file", name});
+ CommandLine commandLine = createCommandLine(new String[] {"--output-file", fileName});
OutputFileConfig configuration = new OutputFileConfig();
ArgumentContext ctxt = new ArgumentContext(new File("."), configuration, commandLine);
Arg.processArgs(ctxt);
- assertEquals(expected.getAbsolutePath(), configuration.actual.getAbsolutePath());
+ assertThat(configuration.actual.getAbsolutePath()).isEqualTo(expected.getCanonicalPath());
}
}
diff --git a/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java b/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java
index d5e70ed74..29d77e962 100644
--- a/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java
+++ b/apache-rat-plugin/src/main/java/org/apache/rat/mp/AbstractRatMojo.java
@@ -105,21 +105,21 @@ public void setAddDefaultLicenses(final boolean addDefaultLicenses) {
/**
* Whether to add the default list of license matchers.
- * @deprecated @deprecated Use specific configuration under <configuration>.
+ * @deprecated Use specific configuration under <configuration>.
*/
@Deprecated
@Parameter(property = "rat.addDefaultLicenseMatchers")
private boolean addDefaultLicenseMatchers;
/** The list of approved licenses
- * @deprecated @deprecated Use specific configuration under <configuration>.
+ * @deprecated Use specific configuration under <configuration>.
*/
@Deprecated
- @Parameter(required = false)
+ @Parameter
private String[] approvedLicenses;
/** The file of approved licenses
- * @deprecated @deprecated Use specific configuration under <configuration>.
+ * @deprecated Use specific configuration under <configuration>.
*/
@Deprecated
@Parameter(property = "rat.approvedFile")
diff --git a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
index cc465da37..6d23f0616 100644
--- a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
+++ b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
@@ -81,7 +81,7 @@ public AntOptionsProvider() {
super(BaseAntTask.unsupportedArgs(), testPath.toFile());
}
- protected ReportConfiguration generateConfig(List> args) {
+ protected final ReportConfiguration generateConfig(List> args) {
BuildTask task = args.get(0).getKey() == null ? new BuildTask() : new BuildTask(args.get(0).getKey());
task.setUp(args);
task.buildRule.executeTarget(task.name);
From e7397ffecdb8704a7139886c87217aaf8dc60bb2 Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Tue, 4 Feb 2025 15:29:56 +0100
Subject: [PATCH 30/41] RAT-98: Add matcher set (#430)
* added working directory
* Added FSInfo to handle file system differences
* fixed pattern match
* added more descriptive failure messages
* added file converter + test
* fixed file list walker
* implemented matcher set in ExclusionProcessor
---------
Co-authored-by: P. Ottlinger
---
.../config/exclusion/ExclusionProcessor.java | 217 ++++++++++--------
.../rat/config/exclusion/ExclusionUtils.java | 66 +++++-
.../rat/config/exclusion/MatcherSet.java | 178 ++++++++++++++
.../config/exclusion/StandardCollection.java | 38 ++-
4 files changed, 384 insertions(+), 115 deletions(-)
create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/exclusion/MatcherSet.java
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
index c1de611ff..d5b3ebe4b 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
@@ -24,8 +24,8 @@
import java.util.Objects;
import java.util.Set;
import java.util.TreeSet;
+import java.util.stream.Collectors;
-import org.apache.rat.config.exclusion.plexus.MatchPatterns;
import org.apache.rat.document.DocumentName;
import org.apache.rat.document.DocumentNameMatcher;
import org.apache.rat.utils.DefaultLog;
@@ -85,10 +85,8 @@ private void resetLastMatcher() {
* @return this
*/
public ExclusionProcessor addIncludedPatterns(final Iterable patterns) {
- List lst = new ArrayList<>();
- patterns.forEach(lst::add);
- DefaultLog.getInstance().info(format("Including patterns: %s", String.join(", ", lst)));
- includedPatterns.addAll(lst);
+ DefaultLog.getInstance().info(format("Including patterns: %s", String.join(", ", patterns)));
+ patterns.forEach(includedPatterns::add);
resetLastMatcher();
return this;
}
@@ -140,10 +138,8 @@ public ExclusionProcessor addIncludedCollection(final StandardCollection collect
* @return this
*/
public ExclusionProcessor addExcludedPatterns(final Iterable patterns) {
- List lst = new ArrayList<>();
- patterns.forEach(lst::add);
- DefaultLog.getInstance().info(format("Excluding patterns: %s", String.join(", ", lst)));
- excludedPatterns.addAll(lst);
+ DefaultLog.getInstance().info(format("Excluding patterns: %s", String.join(", ", patterns)));
+ patterns.forEach(excludedPatterns::add);
resetLastMatcher();
return this;
}
@@ -175,22 +171,6 @@ public ExclusionProcessor addExcludedCollection(final StandardCollection collect
return this;
}
- /**
- * Adds to lists of qualified file patterns. Non-matching patterns start with a {@code !}.
- * @param matching the list to put matching file patterns into.
- * @param notMatching the list to put non-matching files patterns into.
- * @param patterns the patterns to match.
- */
- private void segregateList(final Set matching, final Set notMatching,
- final Iterable patterns) {
- if (patterns.iterator().hasNext()) {
- ExtendedIterator.create(patterns.iterator()).filter(ExclusionUtils.MATCH_FILTER).forEachRemaining(matching::add);
- ExtendedIterator.create(patterns.iterator()).filter(ExclusionUtils.NOT_MATCH_FILTER)
- .map(s -> s.substring(1))
- .forEachRemaining(notMatching::add);
- }
- }
-
/**
* Creates a Document name matcher that will return {@code false} on any
* document that is excluded.
@@ -204,84 +184,137 @@ public DocumentNameMatcher getNameMatcher(final DocumentName basedir) {
if (lastMatcher == null || !basedir.equals(lastMatcherBaseDir)) {
lastMatcherBaseDir = basedir;
- final Set incl = new TreeSet<>();
- final Set excl = new TreeSet<>();
- final List inclMatchers = new ArrayList<>();
-
// add the file processors
- for (StandardCollection sc : fileProcessors) {
- ExtendedIterator iter = sc.fileProcessor();
- if (iter.hasNext()) {
- iter.forEachRemaining(fp -> {
- segregateList(excl, incl, fp.apply(basedir));
- fp.customDocumentNameMatchers().forEach(inclMatchers::add);
- });
- } else {
- DefaultLog.getInstance().info(String.format("%s does not have a fileProcessor.", sc));
- }
- }
+ final List matchers = extractFileProcessors(basedir);
+ final MatcherSet.Builder fromCommandLine = new MatcherSet.Builder();
+ DocumentName.Builder nameBuilder = DocumentName.builder(basedir).setBaseName(basedir);
+ extractPatterns(nameBuilder, fromCommandLine);
+ extractCollectionPatterns(nameBuilder, fromCommandLine);
+ extractCollectionMatchers(fromCommandLine);
+ extractPaths(fromCommandLine);
+ matchers.add(fromCommandLine.build());
- // add the standard patterns
- segregateList(incl, excl, new FileProcessor(includedPatterns).apply(basedir));
- segregateList(excl, incl, new FileProcessor(excludedPatterns).apply(basedir));
+ lastMatcher = MatcherSet.merge(matchers).createMatcher();
+ DefaultLog.getInstance().debug(format("Created matcher set for %s%n%s", basedir.getName(),
+ lastMatcher));
+ }
+ return lastMatcher;
+ }
- // add the collection patterns
- for (StandardCollection sc : includedCollections) {
- Set patterns = sc.patterns();
- if (patterns.isEmpty()) {
- DefaultLog.getInstance().info(String.format("%s does not have a defined collection for inclusion.", sc));
- } else {
- segregateList(incl, excl, new FileProcessor(sc.patterns()).apply(basedir));
- }
- }
- for (StandardCollection sc : excludedCollections) {
- Set patterns = sc.patterns();
- if (patterns.isEmpty()) {
- DefaultLog.getInstance().info(String.format("%s does not have a defined collection for exclusion.", sc));
- } else {
- segregateList(excl, incl, new FileProcessor(sc.patterns()).apply(basedir));
- }
- }
+ /**
+ * Extracts the file processors from {@link #fileProcessors}.
+ * @param basedir The directory to base the file processors on.
+ * @return a list of MatcherSets that are created for each {@link #fileProcessors} entry.
+ */
+ private List extractFileProcessors(final DocumentName basedir) {
+ final List fileProcessorList = new ArrayList<>();
+ for (StandardCollection sc : fileProcessors) {
+ final Set names = new HashSet<>();
+ sc.fileProcessor().map(fp -> fp.apply(basedir)).forEachRemaining(n -> n.forEach(names::add));
+ MatcherSet.Builder builder = new MatcherSet.Builder();
+ Set matching = new HashSet<>();
+ Set notMatching = new HashSet<>();
+ MatcherSet.Builder.segregateList(matching, notMatching, names);
+ builder.addIncluded(basedir.resolve(sc.name()), notMatching);
+ builder.addExcluded(basedir.resolve(sc.name()), matching);
+ fileProcessorList.add(builder.build());
+ }
+ return fileProcessorList;
+ }
- // add the matchers
- ExtendedIterator.create(includedCollections.iterator())
- .map(StandardCollection::staticDocumentNameMatcher)
- .filter(Objects::nonNull)
- .forEachRemaining(inclMatchers::add);
+ /**
+ * Converts the pattern to use the directory separator specified by the document name and localises it for
+ * exclusion processing.
+ * @param documentName The document name to adjust the pattern against.
+ * @param pattern the pattern.
+ * @return the prepared pattern.
+ */
+ private String preparePattern(final DocumentName documentName, final String pattern) {
+ return ExclusionUtils.qualifyPattern(documentName,
+ ExclusionUtils.convertSeparator(pattern, "/", documentName.getDirectorySeparator()));
+ }
- List exclMatchers = ExtendedIterator.create(excludedCollections.iterator())
- .map(StandardCollection::staticDocumentNameMatcher)
- .filter(Objects::nonNull)
- .addTo(new ArrayList<>());
+ /**
+ * Extracts {@link #includedPatterns} and {@link #excludedPatterns} into the specified matcherBuilder.
+ * @param nameBuilder The name builder for the pattern. File names are resolved against the generated name.
+ * @param matcherBuilder the MatcherSet.Builder to add the patterns to.
+ */
+ private void extractPatterns(final DocumentName.Builder nameBuilder, final MatcherSet.Builder matcherBuilder) {
+ DocumentName name = nameBuilder.setName("Patterns").build();
+ if (!excludedPatterns.isEmpty()) {
+ matcherBuilder.addExcluded(name, excludedPatterns.stream()
+ .map(s -> preparePattern(name, s))
+ .collect(Collectors.toSet()));
+ }
+ if (!includedPatterns.isEmpty()) {
+ matcherBuilder.addIncluded(name, includedPatterns.stream()
+ .map(s -> preparePattern(name, s)).collect(Collectors.toSet()));
+ }
+ }
- if (!incl.isEmpty()) {
- inclMatchers.add(new DocumentNameMatcher("included patterns", MatchPatterns.from(basedir.getDirectorySeparator(), incl), basedir));
+ /**
+ * Extracts {@link #includedCollections} and {@link #excludedCollections} patterns into the specified matcherBuilder.
+ * @param nameBuilder the name builder for the pattern names.
+ * @param matcherBuilder the MatcherSet.Builder to add the collections to.
+ */
+ private void extractCollectionPatterns(final DocumentName.Builder nameBuilder, final MatcherSet.Builder matcherBuilder) {
+ final Set incl = new TreeSet<>();
+ final Set excl = new TreeSet<>();
+ for (StandardCollection sc : includedCollections) {
+ Set patterns = sc.patterns();
+ if (patterns.isEmpty()) {
+ DefaultLog.getInstance().debug(String.format("%s does not have a defined collection for inclusion.", sc));
+ } else {
+ MatcherSet.Builder.segregateList(incl, excl, sc.patterns());
}
- if (!excl.isEmpty()) {
- exclMatchers.add(new DocumentNameMatcher("excluded patterns", MatchPatterns.from(basedir.getDirectorySeparator(), excl), basedir));
+ }
+ for (StandardCollection sc : excludedCollections) {
+ Set patterns = sc.patterns();
+ if (patterns.isEmpty()) {
+ DefaultLog.getInstance().debug(String.format("%s does not have a defined collection for exclusion.", sc));
+ } else {
+ MatcherSet.Builder.segregateList(excl, incl, sc.patterns());
}
+ }
+ DocumentName name = nameBuilder.setName("Collections").build();
+ matcherBuilder
+ .addExcluded(name, excl.stream().map(s -> preparePattern(name.getBaseDocumentName(), s)).collect(Collectors.toSet()))
+ .addIncluded(name, incl.stream().map(s -> preparePattern(name.getBaseDocumentName(), s)).collect(Collectors.toSet()));
+ }
- if (!includedPaths.isEmpty()) {
- for (DocumentNameMatcher matcher : includedPaths) {
- DefaultLog.getInstance().info(format("Including path matcher %s", matcher));
- inclMatchers.add(matcher);
- }
- }
- if (!excludedPaths.isEmpty()) {
- for (DocumentNameMatcher matcher : excludedPaths) {
- DefaultLog.getInstance().info(format("Excluding path matcher %s", matcher));
- exclMatchers.add(matcher);
- }
- }
+ /**
+ * Extracts {@link #includedCollections} and {@link #excludedCollections} matchers into the specified matcherBuilder.
+ * @param matcherBuilder the MatcherSet.Builder to add the collections to.
+ */
+ private void extractCollectionMatchers(final MatcherSet.Builder matcherBuilder) {
+ ExtendedIterator.create(includedCollections.iterator())
+ .map(StandardCollection::staticDocumentNameMatcher)
+ .filter(Objects::nonNull)
+ .forEachRemaining(matcherBuilder::addIncluded);
- lastMatcher = DocumentNameMatcher.MATCHES_ALL;
- if (!exclMatchers.isEmpty()) {
- lastMatcher = DocumentNameMatcher.not(DocumentNameMatcher.or(exclMatchers));
- if (!inclMatchers.isEmpty()) {
- lastMatcher = DocumentNameMatcher.or(DocumentNameMatcher.or(inclMatchers), lastMatcher);
- }
+ ExtendedIterator.create(excludedCollections.iterator())
+ .map(StandardCollection::staticDocumentNameMatcher)
+ .filter(Objects::nonNull)
+ .forEachRemaining(matcherBuilder::addExcluded);
+ }
+
+ /**
+ * Extracts {@link #includedPaths} and {@link #excludedPaths} patterns into the specified matcherBuilder.
+ * @param matcherBuilder the MatcherSet.Builder to add the collections to.
+ */
+ private void extractPaths(final MatcherSet.Builder matcherBuilder) {
+ if (!includedPaths.isEmpty()) {
+ for (DocumentNameMatcher matcher : includedPaths) {
+ DefaultLog.getInstance().info(format("Including path matcher %s", matcher));
+ matcherBuilder.addIncluded(matcher);
+ }
+ }
+ if (!excludedPaths.isEmpty()) {
+ for (DocumentNameMatcher matcher : excludedPaths) {
+ DefaultLog.getInstance().info(format("Excluding path matcher %s", matcher));
+ matcherBuilder.addExcluded(matcher);
}
}
- return lastMatcher;
}
+
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionUtils.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionUtils.java
index 7932db4f6..ef2bab1bf 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionUtils.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionUtils.java
@@ -34,9 +34,13 @@
import org.apache.commons.io.LineIterator;
import org.apache.commons.lang3.StringUtils;
import org.apache.rat.ConfigurationException;
+import org.apache.rat.config.exclusion.plexus.MatchPattern;
+import org.apache.rat.config.exclusion.plexus.SelectorUtils;
import org.apache.rat.document.DocumentName;
import org.apache.rat.document.DocumentNameMatcher;
+import org.apache.rat.utils.DefaultLog;
import org.apache.rat.utils.ExtendedIterator;
+import org.apache.rat.utils.Log;
import static java.lang.String.format;
@@ -48,11 +52,14 @@ public final class ExclusionUtils {
/** The list of comment prefixes that are used to filter comment lines. */
public static final List COMMENT_PREFIXES = Arrays.asList("#", "##", "//", "/**", "/*");
- /** A predicate that filters out lines that do NOT start with "!" */
- public static final Predicate NOT_MATCH_FILTER = s -> s.startsWith("!");
+ /** Prefix used to negate a given pattern. */
+ public static final String NEGATION_PREFIX = "!";
- /** A predicate that filters out lines that start with "!" */
- public static final Predicate MATCH_FILTER = s -> !s.startsWith("!");
+ /** A predicate that filters out lines that do NOT start with {@link #NEGATION_PREFIX}. */
+ public static final Predicate NOT_MATCH_FILTER = s -> s.startsWith(NEGATION_PREFIX);
+
+ /** A predicate that filters out lines that start with {@link #NEGATION_PREFIX}. */
+ public static final Predicate MATCH_FILTER = NOT_MATCH_FILTER.negate();
private ExclusionUtils() {
// do not instantiate
@@ -112,7 +119,20 @@ public static Predicate commentFilter(final String commentPrefix) {
* @return a FileFilter.
*/
public static FileFilter asFileFilter(final DocumentName parent, final DocumentNameMatcher nameMatcher) {
- return file -> nameMatcher.matches(DocumentName.builder(file).setBaseName(parent.getBaseName()).build());
+ return file -> {
+ DocumentName candidate = DocumentName.builder(file).setBaseName(parent.getBaseName()).build();
+ boolean result = nameMatcher.matches(candidate);
+ Log log = DefaultLog.getInstance();
+ if (log.isEnabled(Log.Level.DEBUG)) {
+ log.debug(format("FILTER TEST for %s -> %s", file, result));
+ if (!result) {
+ List< DocumentNameMatcher.DecomposeData> data = nameMatcher.decompose(candidate);
+ log.debug("Decomposition for " + candidate);
+ data.forEach(log::debug);
+ }
+ }
+ return result;
+ };
}
/**
@@ -171,13 +191,12 @@ protected boolean isValidLine(final String line) {
}
/**
- * Returns {@code true} if the file name represents a hidden file.
- * @param f the file to check.
- * @return {@code true} if it is the name of a hidden file.
+ * Returns {@code true} if the filename represents a hidden file
+ * @param fileName the file to check.
+ * @return true if it is the name of a hidden file.
*/
- public static boolean isHidden(final File f) {
- String s = f.getName();
- return s.startsWith(".") && !(s.equals(".") || s.equals(".."));
+ public static boolean isHidden(final String fileName) {
+ return fileName.startsWith(".") && !(fileName.equals(".") || fileName.equals(".."));
}
private static void verifyFile(final File file) {
@@ -186,6 +205,31 @@ private static void verifyFile(final File file) {
}
}
+ /**
+ * Modifies the {@link MatchPattern} formatted {@code pattern} argument by expanding the pattern and
+ * by adjusting the pattern to include the basename from the {@code documentName} argument.
+ * @param documentName the name of the file being read.
+ * @param pattern the pattern to format.
+ * @return the completely formatted pattern
+ */
+ public static String qualifyPattern(final DocumentName documentName, final String pattern) {
+ boolean prefix = pattern.startsWith(NEGATION_PREFIX);
+ String workingPattern = prefix ? pattern.substring(1) : pattern;
+ String normalizedPattern = SelectorUtils.extractPattern(workingPattern, documentName.getDirectorySeparator());
+
+ StringBuilder sb = new StringBuilder(prefix ? NEGATION_PREFIX : "");
+ if (SelectorUtils.isRegexPrefixedPattern(workingPattern)) {
+ sb.append(SelectorUtils.REGEX_HANDLER_PREFIX)
+ .append("\\Q").append(documentName.getBaseName())
+ .append(documentName.getDirectorySeparator())
+ .append("\\E").append(normalizedPattern)
+ .append(SelectorUtils.PATTERN_HANDLER_SUFFIX);
+ } else {
+ sb.append(documentName.getBaseDocumentName().resolve(normalizedPattern).getName());
+ }
+ return sb.toString();
+ }
+
/**
* Tokenizes the string based on the directory separator.
* @param source the source to tokenize.
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/MatcherSet.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/MatcherSet.java
new file mode 100644
index 000000000..5224fa6fa
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/MatcherSet.java
@@ -0,0 +1,178 @@
+/*
+ * 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.exclusion;
+
+import java.util.List;
+import java.util.Optional;
+import java.util.Set;
+import java.util.function.Consumer;
+
+import org.apache.rat.config.exclusion.plexus.MatchPattern;
+import org.apache.rat.config.exclusion.plexus.MatchPatterns;
+import org.apache.rat.config.exclusion.plexus.SelectorUtils;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+
+import static org.apache.rat.document.DocumentNameMatcher.MATCHES_NONE;
+
+/**
+ * The file processor reads the file specified in the DocumentName.
+ * It must return a list of fully qualified strings for the {@link MatchPattern} to process.
+ * It may return either Ant or Regex style strings, or a mixture of both.
+ * See {@link SelectorUtils} for a description of the formats.
+ * It may also generate custom DocumentNameMatchers which are added to the customMatchers instance variable.
+ */
+public interface MatcherSet {
+ Optional includes();
+ Optional excludes();
+
+ default String getDescription() {
+ return String.format("MatcherSet: include [%s] exclude [%s]", includes().orElse(MATCHES_NONE), excludes().orElse(MATCHES_NONE));
+ }
+ /**
+ * Creates a DocumentNameMatcher from an iterable of matcher sets.
+ * @return A DocumentNameMatcher that processes the matcher sets.
+ */
+ default DocumentNameMatcher createMatcher() {
+ return DocumentNameMatcher.matcherSet(includes().orElse(MATCHES_NONE), excludes().orElse(MATCHES_NONE));
+ }
+
+ static MatcherSet merge(List matcherSets) {
+ Builder builder = new Builder();
+ for (MatcherSet matcherSet : matcherSets) {
+ matcherSet.includes().ifPresent(builder::addIncluded);
+ matcherSet.excludes().ifPresent(builder::addExcluded);
+ }
+ return builder.build();
+ }
+
+ /**
+ * A MatcherSet that assumes the files contain the already formatted strings and just need to be
+ * localised for the fileName. When {@link #build()} is called the builder is reset to the initial state.
+ */
+ class Builder {
+
+ /**
+ * Adds to lists of qualified file patterns. Non-matching patterns start with a {@link ExclusionUtils#NEGATION_PREFIX}.
+ * @param matching the list to put matching file patterns into.
+ * @param notMatching the list to put non-matching file patterns into.
+ * @param patterns the patterns to match.
+ */
+ public static void segregateList(final Set matching, final Set notMatching,
+ final Iterable patterns) {
+ patterns.forEach(s -> {
+ if (ExclusionUtils.MATCH_FILTER.test(s)) {
+ matching.add(s);
+ } else {
+ notMatching.add(s.substring(1));
+ }
+ });
+ }
+
+ /** The DocumentNameMatcher that specifies included files */
+ protected DocumentNameMatcher included;
+ /** The DocumentNameMatcher that specifies excluded files */
+ protected DocumentNameMatcher excluded;
+
+ public Builder() {
+ }
+
+ /**
+ * Converts a collection names into DocumentNameMatchers that use the {@code fromDocument} directory separator.
+ * @param dest the consumer to accept the DocumentNameMatcher.
+ * @param nameFormat the format for the matcher names. Requires '%s' for the {@code fromDocument} localised name.
+ * @param fromDocument the document that the patterns are associated with.
+ * @param names the list of patterns. If empty no action is taken.
+ */
+ private void processNames(final Consumer dest, final String nameFormat, final DocumentName fromDocument, final Set names) {
+ if (!names.isEmpty()) {
+ String name = String.format(nameFormat, fromDocument.localized("/").substring(1));
+ dest.accept(new DocumentNameMatcher(name, MatchPatterns.from(fromDocument.getDirectorySeparator(), names), fromDocument.getBaseDocumentName()));
+ }
+ }
+
+ /**
+ * Adds included file names from the specified document. File names are resolved relative to the directory
+ * of the {@code fromDocument}.
+ * @param fromDocument the document the names were read from.
+ * @param names the names that were read from the document. Must use the separator specified by {@code fromDocument}.
+ * @return this
+ */
+ public Builder addIncluded(final DocumentName fromDocument, final Set names) {
+ processNames(this::addIncluded, "'included %s'", fromDocument, names);
+ return this;
+ }
+
+ /**
+ * Adds excluded file names from the specified document. File names are resolved relative to the directory
+ * of the {@code fromDocument}.
+ * @param fromDocument the document the names were read from.
+ * @param names the names that were read from the document. Must use the separator specified by {@code fromDocument}.
+ * @return this
+ */
+ public Builder addExcluded(final DocumentName fromDocument, final Set names) {
+ processNames(this::addExcluded, "'excluded %s'", fromDocument, names);
+ return this;
+ }
+
+ /**
+ * Adds specified DocumentNameMatcher to the included matchers.
+ * @param matcher A document name matcher to add to the included set.
+ * @return this
+ */
+ public Builder addIncluded(final DocumentNameMatcher matcher) {
+ this.included = this.included == null ? matcher : DocumentNameMatcher.or(this.included, matcher);
+ return this;
+ }
+
+ /**
+ * Adds specified DocumentNameMatcher to the excluded matchers.
+ * @param matcher A document name matcher to add to the excluded set.
+ * @return this
+ */
+ public Builder addExcluded(final DocumentNameMatcher matcher) {
+ this.excluded = this.excluded == null ? matcher : DocumentNameMatcher.or(this.excluded, matcher);
+ return this;
+ }
+
+ /**
+ * Builds a MatcherSet. When {@code build()} is called the builder is reset to the initial state.
+ * @return the MatcherSet based upon the included and excluded matchers.
+ */
+ public MatcherSet build() {
+ MatcherSet result = new MatcherSet() {
+ private final DocumentNameMatcher myIncluded = included;
+ private final DocumentNameMatcher myExcluded = excluded;
+
+ @Override
+ public Optional includes() {
+ return Optional.ofNullable(myIncluded);
+ }
+
+ @Override
+ public Optional excludes() {
+ return Optional.ofNullable(myExcluded);
+ }
+ };
+ included = null;
+ excluded = null;
+ return result;
+ }
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
index 1bd805f41..d2c59707c 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
@@ -96,24 +96,38 @@ null, new CVSFileProcessor()),
new GitFileProcessor()
),
/**
- * The hidden directories. Directories with names that start with '.'
+ * The hidden directories. Directories with names that start with {@code .}
*/
HIDDEN_DIR("The hidden directories. Directories with names that start with '.'",
null,
- new DocumentNameMatcher("HIDDEN_DIR", (Predicate) documentName -> {
- File f = new File(documentName.getName());
- return f.isDirectory() && ExclusionUtils.isHidden(f);
- }), null
+ new DocumentNameMatcher("HIDDEN_DIR", new Predicate() {
+ @Override
+ public boolean test(final DocumentName documentName) {
+ File file = documentName.asFile();
+ return file.isDirectory() && ExclusionUtils.isHidden(documentName.getShortName());
+ }
+ @Override
+ public String toString() {
+ return "HIDDEN_DIR";
+ }
+ }), null
),
/**
- * The hidden files. Directories with names that start with '.'
+ * The hidden files. Directories with names that start with {@code .}
*/
HIDDEN_FILE("The hidden files. Directories with names that start with '.'",
null,
- new DocumentNameMatcher("HIDDEN_FILE", (Predicate) documentName -> {
- File f = new File(documentName.getName());
- return f.isFile() && ExclusionUtils.isHidden(f);
- }), null
+ new DocumentNameMatcher("HIDDEN_FILE", new Predicate() {
+ @Override
+ public boolean test(final DocumentName documentName) {
+ File file = documentName.asFile();
+ return file.isFile() && ExclusionUtils.isHidden(documentName.getShortName());
+ }
+ @Override
+ public String toString() {
+ return "HIDDEN_FILE";
+ }
+ }), null
),
/**
* The files and directories created by an IDEA IDE based tool.
@@ -121,9 +135,9 @@ null, new CVSFileProcessor()),
IDEA("The files and directories created by an IDEA IDE based tool.",
Arrays.asList("**/*.iml", "**/*.ipr", "**/*.iws", "**/.idea/**"), null, null),
/**
- * The .DS_Store files MAC computer.
+ * The .DS_Store files on Mac computers.
*/
- MAC("The .DS_Store files MAC computer.",
+ MAC("The .DS_Store files Mac computers.",
Collections.singletonList("**/.DS_Store"), null, null),
/**
* The files and directories created by Maven build system based project.
From cd9aeaf07f7cd70685ae93ed41efd543e296236f Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Thu, 6 Feb 2025 14:48:26 +0100
Subject: [PATCH 31/41] RAT-98: updated tests (#437)
* updated tests
---------
Co-authored-by: P. Ottlinger
---
.../org/apache/rat/OptionCollectionTest.java | 20 +--
.../rat/document/DocumentNameBuilderTest.java | 167 ++++++++++++++++++
2 files changed, 169 insertions(+), 18 deletions(-)
create mode 100644 apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java
diff --git a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
index c0d45c08a..7f34fa2ee 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/OptionCollectionTest.java
@@ -53,10 +53,9 @@
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.fail;
+import static org.assertj.core.api.Fail.fail;
public class OptionCollectionTest {
-
@TempDir
static Path testPath;
@@ -65,21 +64,6 @@ static void preserveData() {
AbstractOptionsProvider.preserveData(testPath.toFile(), "optionTest");
}
- /**
- * The base directory for the test.
- * We do not use TempFile because we want the evidence of the run
- * to exist after a failure.
- */
- private final File baseDir;
-
- /**
- * Constructor.
- */
- public OptionCollectionTest() {
- baseDir = new File("target/optionTools");
- baseDir.mkdirs();
- }
-
/**
* Defines the test method that is stored in a map.
*/
@@ -128,7 +112,7 @@ public void testDirOptionCapturesDirectoryToScan() throws IOException {
ReportConfiguration config;
try {
DefaultLog.setInstance(log);
- String[] args = {"--dir", baseDir.getAbsolutePath()};
+ String[] args = {"--dir", testPath.toFile().getAbsolutePath()};
config = OptionCollection.parseCommands(testPath.toFile(), args, (o) -> {
}, true);
} finally {
diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java
new file mode 100644
index 000000000..0e0f0d1f7
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/document/DocumentNameBuilderTest.java
@@ -0,0 +1,167 @@
+/*
+ * 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.document;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+import static org.apache.rat.document.FSInfoTest.WINDOWS;
+
+public class DocumentNameBuilderTest {
+
+ @ParameterizedTest(name="{0}")
+ @MethodSource("buildTestData")
+ void buildTest(String testName, DocumentName documentName, String name, String shortName, String baseName, String root,
+ String directorySeparator, Boolean isCaseSensitive, String localized, String localizedArg) {
+ assertThat(documentName.getName()).as("Invalid name").isEqualTo(name);
+ assertThat(documentName.getShortName()).as("Invalid short name").isEqualTo(shortName);
+ assertThat(documentName.getBaseName()).as("Invalid base name").isEqualTo(baseName);
+ assertThat(documentName.getRoot()).as("Invalid root").isEqualTo(root);
+ assertThat(documentName.getDirectorySeparator()).as("Invalid directory separator").isEqualTo(directorySeparator);
+ if (isCaseSensitive) {
+ assertThat(documentName.isCaseSensitive()).as("Invalid case sensitivity").isTrue();
+ } else {
+ assertThat(documentName.isCaseSensitive()).as("Invalid case sensitivity").isFalse();
+ }
+ assertThat(documentName.localized()).as("Invalid localized ").isEqualTo(localized);
+ final String sep = documentName.getDirectorySeparator().equals("/") ? "\\" : "/";
+ assertThat(documentName.localized(sep)).as(() -> String.format("Invalid localized('%s')", sep)).isEqualTo(localizedArg);
+ }
+
+ static Stream buildTestData() {
+ List lst = new ArrayList<>();
+
+ //
+ String testName = "windows\\foo direct";
+ DocumentName documentName = DocumentName.builder(WINDOWS).setName("C:\\windows\\foo").setBaseName("C:\\windows").build();
+ lst.add(Arguments.of( testName, documentName, "C:\\windows\\foo", "foo", "C:\\windows", "C:", "\\", false,
+ "\\foo", "/foo"));
+ DocumentName baseName = documentName;
+
+ //
+ testName = "builder(docName)";
+ documentName = DocumentName.builder(baseName).build();
+ lst.add(Arguments.of( testName, documentName, "C:\\windows\\foo", "foo", "C:\\windows", "C:", "\\", false,
+ "\\foo", "/foo"));
+
+ //
+ testName = "windows\\foo\\bar by resolve";
+ documentName = baseName.resolve("bar");
+ lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows", "C:", "\\", false,
+ "\\foo\\bar", "/foo/bar"));
+
+ //
+ testName = "windows\\foo\\direct by basename";
+ documentName = DocumentName.builder(baseName).setName("windows\\foo\\direct").build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\direct", "direct", "C:\\windows", "C:", "\\", false,
+ "\\foo\\direct", "/foo/direct"));
+
+ //
+ testName = "windows\\foo\\bar by file";
+ File file = mock(File.class);
+ File parent = mock(File.class);
+ when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar");
+ when(file.getParentFile()).thenReturn(parent);
+ when(file.isDirectory()).thenReturn(false);
+ when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo");
+ when(parent.isDirectory()).thenReturn(true);
+ documentName = new DocumentName.Builder(WINDOWS, file).build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo", "C:", "\\", false,
+ "\\bar", "/bar"));
+
+ //
+ testName = "windows\\foo\\bar by directory";
+ file = mock(File.class);
+ parent = mock(File.class);
+ when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar");
+ when(file.getParentFile()).thenReturn(parent);
+ when(file.isDirectory()).thenReturn(true);
+ when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo");
+ when(parent.isDirectory()).thenReturn(true);
+ documentName = new DocumentName.Builder(WINDOWS, file).build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo\\bar", "C:", "\\", false,
+ "\\", "/"));
+
+ //
+ testName = "windows setRoot";
+ documentName = DocumentName.builder(baseName).setRoot("D:").build();
+ lst.add(Arguments.of(testName, documentName, "D:\\windows\\foo", "foo", "C:\\windows", "D:", "\\", false,
+ "D:\\windows\\foo", "D:/windows/foo"));
+
+ testName = "windows setRoot(null)";
+ documentName = DocumentName.builder(baseName).setRoot(null).build();
+ lst.add(Arguments.of(testName, documentName, "\\windows\\foo", "foo", "C:\\windows", "", "\\", false,
+ "\\windows\\foo", "/windows/foo"));
+
+ testName = "windows setRoot('')";
+ documentName = DocumentName.builder(baseName).setRoot("").build();
+ lst.add(Arguments.of(testName, documentName, "\\windows\\foo", "foo", "C:\\windows", "", "\\", false,
+ "\\windows\\foo", "/windows/foo"));
+
+ //
+ testName = "windows setName('baz')";
+ documentName = DocumentName.builder(baseName).setName("baz").build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows\\baz", "baz", "C:\\windows", "C:", "\\", false,
+ "\\baz", "/baz"));
+
+ testName = "windows setName((String)null)";
+ documentName = DocumentName.builder(baseName).setName((String)null).build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows", "windows", "C:\\windows", "C:", "\\", false,
+ "\\", "/"));
+
+ testName = "windows setName('')";
+ documentName = DocumentName.builder(baseName).setName("").build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows", "windows", "C:\\windows", "C:", "\\", false,
+ "\\", "/"));
+
+ file = mock(File.class);
+ parent = mock(File.class);
+ when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar");
+ when(file.getParentFile()).thenReturn(parent);
+ when(file.isDirectory()).thenReturn(false);
+ when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo");
+ when(parent.isDirectory()).thenReturn(true);
+ testName = "windows setName(file)";
+ documentName = DocumentName.builder(baseName).setName(file).build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo", "C:", "\\", false,
+ "\\bar", "/bar"));
+
+ file = mock(File.class);
+ parent = mock(File.class);
+ when(file.getAbsolutePath()).thenReturn("C:\\windows\\foo\\bar");
+ when(file.getParentFile()).thenReturn(parent);
+ when(file.isDirectory()).thenReturn(true);
+ when(parent.getAbsolutePath()).thenReturn("C:\\windows\\foo");
+ when(parent.isDirectory()).thenReturn(true);
+ testName = "windows setName(directory)";
+ documentName = DocumentName.builder(baseName).setName(file).build();
+ lst.add(Arguments.of(testName, documentName, "C:\\windows\\foo\\bar", "bar", "C:\\windows\\foo\\bar", "C:", "\\", false,
+ "\\", "/"));
+
+ return lst.stream();
+ }
+}
From 5066aa0c74be905558ce3f654c478d440626ea7d Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Fri, 7 Feb 2025 09:22:17 +0100
Subject: [PATCH 32/41] RAT-98: converted to assertj (#438)
* converted to assertj
* Disabled gitignore tests
---------
Co-authored-by: P. Ottlinger
---
.../apache/rat/ReportConfigurationTest.java | 109 ++---
.../apache/rat/document/FileDocumentTest.java | 33 +-
.../org/apache/rat/mp/RatCheckMojoTest.java | 388 +++++++++---------
.../unit/RAT-335-GitIgnore/.gitignore | 7 -
.../unit/RAT-335-GitIgnore/dir1/.gitignore | 3 -
.../unit/RAT-335-GitIgnore/dir1/dir1.txt | 1 -
.../unit/RAT-335-GitIgnore/dir1/file1.log | 1 -
.../unit/RAT-335-GitIgnore/dir2/dir2.md | 1 -
.../unit/RAT-335-GitIgnore/dir3/dir3.log | 1 -
.../resources/unit/RAT-335-GitIgnore/root.md | 1 -
.../{RAT-335-GitIgnore => RAT-335}/README.txt | 0
.../dir1/dir1.md | 0
.../dir2/dir2.txt | 0
.../dir3/file3.log | 0
.../invoker.properties | 0
.../{RAT-335-GitIgnore => RAT-335}/pom.xml | 0
.../unit/RAT-362-GitIgnore/.gitignore | 2 -
.../resources/unit/RAT-362-GitIgnore/foo.md | 1 -
.../{RAT-362-GitIgnore => RAT-362}/bar.md | 0
.../invoker.properties | 0
.../{RAT-362-GitIgnore => RAT-362}/pom.xml | 1 +
.../src/test/resources/unit/it3/pom.xml | 1 +
22 files changed, 270 insertions(+), 280 deletions(-)
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.txt
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/file1.log
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.md
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/dir3.log
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/root.md
rename apache-rat-plugin/src/test/resources/unit/{RAT-335-GitIgnore => RAT-335}/README.txt (100%)
rename apache-rat-plugin/src/test/resources/unit/{RAT-335-GitIgnore => RAT-335}/dir1/dir1.md (100%)
rename apache-rat-plugin/src/test/resources/unit/{RAT-335-GitIgnore => RAT-335}/dir2/dir2.txt (100%)
rename apache-rat-plugin/src/test/resources/unit/{RAT-335-GitIgnore => RAT-335}/dir3/file3.log (100%)
rename apache-rat-plugin/src/test/resources/unit/{RAT-335-GitIgnore => RAT-335}/invoker.properties (100%)
rename apache-rat-plugin/src/test/resources/unit/{RAT-335-GitIgnore => RAT-335}/pom.xml (100%)
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/.gitignore
delete mode 100644 apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/foo.md
rename apache-rat-plugin/src/test/resources/unit/{RAT-362-GitIgnore => RAT-362}/bar.md (100%)
rename apache-rat-plugin/src/test/resources/unit/{RAT-362-GitIgnore => RAT-362}/invoker.properties (100%)
rename apache-rat-plugin/src/test/resources/unit/{RAT-362-GitIgnore => RAT-362}/pom.xml (97%)
diff --git a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java
index 327aa9051..8ff47a287 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/ReportConfigurationTest.java
@@ -19,10 +19,7 @@
package org.apache.rat;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertFalse;
-import static org.junit.jupiter.api.Assertions.assertThrows;
-import static org.junit.jupiter.api.Assertions.assertTrue;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -89,12 +86,15 @@ public void cleanup() {
@Test
public void testAddIncludedFilter() {
+ DocumentName dirName = DocumentName.builder(tempDir).build();
underTest.addExcludedFilter(DirectoryFileFilter.INSTANCE);
- DocumentNameMatcher exlcuder = underTest.getDocumentExcluder(DocumentName.builder(new File(File.separator)).build());
- assertEquals("not(DirectoryFileFilter)", exlcuder.toString());
- assertFalse(exlcuder.matches(DocumentName.builder(tempDir).build()));
+ DocumentNameMatcher excluder = underTest.getDocumentExcluder(dirName);
+
+ assertThat(excluder.toString()).isEqualTo("not(DirectoryFileFilter)");
+ assertThat(excluder.matches(DocumentName.builder(tempDir).build())).isFalse();
+
File f = new File(tempDir, "foo.txt");
- assertTrue(exlcuder.matches(DocumentName.builder(f).build()));
+ assertThat(excluder.matches(DocumentName.builder(f).build())).isTrue();
}
@Test
@@ -103,17 +103,16 @@ public void testAddFamilies() {
ILicenseFamily fam2 = ILicenseFamily.builder().setLicenseFamilyCategory("BAR").setLicenseFamilyName("big and round").build();
underTest.addFamilies(Arrays.asList(fam1, fam2));
SortedSet result = underTest.getLicenseIds(LicenseFilter.ALL);
- assertTrue(result.contains(ILicenseFamily.makeCategory("FOO")), "Missing FOO");
- assertTrue(result.contains(ILicenseFamily.makeCategory("BAR")), "Missing BAR");
- assertEquals(2, result.size());
+ assertThat(result).contains(ILicenseFamily.makeCategory("FOO"));
+ assertThat(result).contains(ILicenseFamily.makeCategory("BAR"));
+ assertThat(result).hasSize(2);
}
@Test
public void testAddApprovedLicenseId() {
underTest.addApprovedLicenseId("FOO");
SortedSet result = underTest.getLicenseIds(LicenseFilter.APPROVED);
- assertTrue(result.contains("FOO"));
- assertEquals(1, result.size());
+ assertThat(result).hasSize(1).contains("FOO");
}
@Test
public void testAddAndRemoveApproveLicenseCategories() {
@@ -366,27 +365,28 @@ DocumentName mkDocumentName(File f) {
@Test
public void exclusionTest() {
DocumentName baseDir = DocumentName.builder(tempDir).build();
- assertTrue(underTest.getDocumentExcluder(baseDir).matches(mkDocumentName(new File(tempDir,"foo"))));
- assertTrue(underTest.getDocumentExcluder(baseDir).matches(mkDocumentName(new File("foo"))));
+ DocumentName foo = mkDocumentName(new File(tempDir,"foo"));
+ assertThat(underTest.getDocumentExcluder(baseDir).matches(foo)).isTrue();
underTest.setFrom(Defaults.builder().build());
File f = new File(tempDir, ".hiddenDir");
- assertTrue(f.mkdir(), () -> "Could not create directory " + f);
-
- assertFalse(underTest.getDocumentExcluder(baseDir).matches(mkDocumentName(new File(tempDir, ".hiddenDir"))));
+ assertThat(f.mkdir()).as(() -> "Could not create directory " + f).isTrue();
+ DocumentName hiddenDir = mkDocumentName(new File(tempDir, ".hiddenDir"));
+ DocumentNameMatcher excluder = underTest.getDocumentExcluder(baseDir);
+ assertThat(excluder.matches(hiddenDir)).isFalse();
underTest.addIncludedCollection(StandardCollection.HIDDEN_DIR);
- assertTrue(underTest.getDocumentExcluder(baseDir).matches(mkDocumentName(new File(tempDir, ".hiddenDir"))));
+ assertThat(underTest.getDocumentExcluder(baseDir).matches(hiddenDir)).isTrue();
underTest.addExcludedCollection(StandardCollection.HIDDEN_DIR);
- assertTrue(underTest.getDocumentExcluder(baseDir).matches(mkDocumentName(new File(tempDir, ".hiddenDir"))));
+ assertThat(underTest.getDocumentExcluder(baseDir).matches(hiddenDir)).isTrue();
underTest.addExcludedFilter(DirectoryFileFilter.DIRECTORY);
File file = new File(tempDir, "newDir");
- assertTrue(file.mkdirs(), () -> "Could not create directory " + file);
- assertFalse(underTest.getDocumentExcluder(baseDir).matches(mkDocumentName(file)));
+ assertThat(file.mkdirs()).as(() -> "Could not create directory " + file).isTrue();
+ assertThat(underTest.getDocumentExcluder(baseDir).matches(mkDocumentName(file))).isFalse();
}
@Test
@@ -471,8 +471,8 @@ public void reportableTest() {
IReportable reportable = mock(IReportable.class);
underTest.addSource(reportable);
assertThat(underTest.hasSource()).isTrue();
- Exception thrown = assertThrows(ConfigurationException.class, () -> underTest.addSource((IReportable)null));
- assertThat(thrown.getMessage()).contains("Reportable may not be null.");
+ assertThatThrownBy(() -> underTest.addSource((IReportable)null)).isExactlyInstanceOf(ConfigurationException.class)
+ .hasMessageContaining("Reportable may not be null.");
}
@Test
@@ -517,18 +517,17 @@ public void testFlags() {
public void testValidate() {
final StringBuilder sb = new StringBuilder();
String msg = "At least one source must be specified";
- Exception thrown = assertThrows(ConfigurationException.class,
- () -> underTest.validate(sb::append));
- assertThat(thrown.getMessage()).isEqualTo(msg);
+ assertThatThrownBy(() -> underTest.validate(sb::append)).isExactlyInstanceOf(ConfigurationException.class)
+ .hasMessageContaining(msg);
assertThat(sb.toString()).isEqualTo(msg);
sb.setLength(0);
msg = "You must specify at least one license";
underTest.addSource(mock(IReportable.class));
- thrown = assertThrows(ConfigurationException.class,
- () -> underTest.validate(sb::append));
- assertThat(thrown.getMessage()).isEqualTo(msg);
+
+ assertThatThrownBy(() -> underTest.validate(sb::append)).isExactlyInstanceOf(ConfigurationException.class)
+ .hasMessageContaining(msg);
assertThat(sb.toString()).isEqualTo(msg);
sb.setLength(0);
@@ -544,10 +543,12 @@ public void testSetOut() throws IOException {
config.setOut(() -> osi);
assertThat(osi.closeCount).isEqualTo(0);
try (OutputStream os = config.getOutput().get()) {
+ assertThat(os).isNotNull();
assertThat(osi.closeCount).isEqualTo(0);
}
assertThat(osi.closeCount).isEqualTo(1);
try (OutputStream os = config.getOutput().get()) {
+ assertThat(os).isNotNull();
assertThat(osi.closeCount).isEqualTo(1);
}
assertThat(osi.closeCount).isEqualTo(2);
@@ -558,45 +559,48 @@ public void testSetOut() throws IOException {
public void logFamilyCollisionTest() {
// setup
underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name"));
- assertFalse(log.getCaptured().contains("CAT"));
+ assertThat(log.getCaptured()).doesNotContain("CAT");
// verify default collision logs WARNING
underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
- assertTrue(log.getCaptured().contains("WARN"), "default value not WARN");
- assertTrue(log.getCaptured().contains("CAT"), "'CAT' not found");
+ assertThat(log.getCaptured().contains("WARN")).as("default value not WARN").isTrue();
+ assertThat(log.getCaptured().contains("CAT")).as("'CAT' not found").isTrue();
// verify level setting works.
for (Level l : Level.values()) {
log.clear();
underTest.logFamilyCollisions(l);
underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
- assertTrue(log.getCaptured().contains("CAT"), "'CAT' not found");
- assertTrue(log.getCaptured().contains(l.name()), "logging not set to "+l);
+ assertThat(log.getCaptured().contains("CAT")).as("'CAT' not found").isTrue();
+ assertThat(log.getCaptured().contains(l.name())).as("logging not set to "+l).isTrue();
}
}
@Test
public void familyDuplicateOptionsTest() {
underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name"));
- assertFalse(log.getCaptured().contains("CAT"));
+ assertThat(log.getCaptured()).doesNotContain("CAT");
// verify default second setting ignores change
underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
- assertTrue(log.getCaptured().contains("CAT"));
- assertEquals("name", underTest.getLicenseFamilies(LicenseFilter.ALL).stream()
- .filter(s -> s.getFamilyCategory().equals("CAT ")).map(ILicenseFamily::getFamilyName).findFirst().get());
+ assertThat(log.getCaptured()).contains("CAT");
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.ALL).stream()
+ .filter(s -> s.getFamilyCategory().equals("CAT ")).map(ILicenseFamily::getFamilyName).findFirst())
+ .contains("name");
underTest.familyDuplicateOption(Options.OVERWRITE);
// verify second setting ignores change
underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2"));
- assertTrue(log.getCaptured().contains("CAT"));
- assertEquals("name2", underTest.getLicenseFamilies(LicenseFilter.ALL).stream()
- .filter(s -> s.getFamilyCategory().equals("CAT ")).map(ILicenseFamily::getFamilyName).findFirst().get());
+ assertThat(log.getCaptured()).contains("CAT");
+ assertThat(underTest.getLicenseFamilies(LicenseFilter.ALL).stream()
+ .filter(s -> s.getFamilyCategory().equals("CAT ")).map(ILicenseFamily::getFamilyName).findFirst())
+ .contains("name2");
// verify fail throws exception
underTest.familyDuplicateOption(Options.FAIL);
- assertThrows( IllegalArgumentException.class, ()->underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2")));
-
+ assertThatThrownBy(()->underTest.addFamily(ILicenseFamily.builder().setLicenseFamilyCategory("CAT").setLicenseFamilyName("name2")))
+ .isExactlyInstanceOf(IllegalArgumentException.class);
+
underTest.familyDuplicateOption(Options.IGNORE);
}
@@ -616,7 +620,7 @@ public void logLicenseCollisionTest() {
underTest.addLicense(ILicense.builder().setId("ID").setName("license name2").setFamily(family.getFamilyCategory())
.setMatcher( matcher ).setLicenseFamilies(underTest.getLicenseFamilies(LicenseFilter.ALL))
.build());
- assertTrue(log.getCaptured().contains("WARN"));
+ assertThat(log.getCaptured()).contains("WARN");
log.clear();
underTest.logLicenseCollisions(Level.ERROR);
@@ -625,7 +629,7 @@ public void logLicenseCollisionTest() {
underTest.addLicense(ILicense.builder().setId("ID").setName("license name2").setFamily(family.getFamilyCategory())
.setMatcher( matcher ).setLicenseFamilies(underTest.getLicenseFamilies(LicenseFilter.ALL))
.build());
- assertTrue(log.getCaptured().contains("ERROR"));
+ assertThat(log.getCaptured()).contains("ERROR");
}
@Test
@@ -643,18 +647,19 @@ public void licenseDuplicateOptionsTest() {
// verify default second setting ignores change
underTest.addLicense(makeLicense.apply("license name2"));
- assertTrue(log.getCaptured().contains("WARN"));
- assertEquals("license name",
- underTest.getLicenses(LicenseFilter.ALL).stream().map(ILicense::getName).findFirst().get());
+ assertThat(log.getCaptured()).contains("WARN");
+ assertThat(underTest.getLicenses(LicenseFilter.ALL).stream().map(ILicense::getName).findFirst())
+ .contains("license name");
underTest.licenseDuplicateOption(Options.OVERWRITE);
underTest.addLicense(makeLicense.apply("license name2"));
- assertEquals("license name2",
- underTest.getLicenses(LicenseFilter.ALL).stream().map(ILicense::getName).findFirst().get());
+ assertThat(underTest.getLicenses(LicenseFilter.ALL).stream().map(ILicense::getName).findFirst())
+ .contains("license name2");
// verify fail throws exception
underTest.licenseDuplicateOption(Options.FAIL);
- assertThrows( IllegalArgumentException.class, ()-> underTest.addLicense(makeLicense.apply("another name")));
+ assertThatThrownBy(()-> underTest.addLicense(makeLicense.apply("another name")))
+ .isExactlyInstanceOf(IllegalArgumentException.class);
}
/**
diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/FileDocumentTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/FileDocumentTest.java
index f1ebb38cf..a36944f4e 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/document/FileDocumentTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/document/FileDocumentTest.java
@@ -18,41 +18,50 @@
*/
package org.apache.rat.document;
+import java.nio.file.Path;
+import org.apache.commons.io.FileUtils;
import org.apache.rat.api.Document;
import org.apache.rat.test.utils.Resources;
-import org.assertj.core.util.Files;
import org.junit.jupiter.api.BeforeEach;
import org.junit.jupiter.api.Test;
import java.io.BufferedReader;
import java.io.File;
import java.io.Reader;
+import org.junit.jupiter.api.io.TempDir;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-import static org.junit.jupiter.api.Assertions.assertNotNull;
+import static org.assertj.core.api.Assertions.assertThat;
public class FileDocumentTest {
private Document document;
- private File file;
-
+
+ @TempDir
+ private static Path tempDir;
+
@BeforeEach
public void setUp() throws Exception {
- File basedir = new File(Files.currentFolder(), Resources.SRC_TEST_RESOURCES);
- file = Resources.getExampleResource("exampleData/Source.java");
- document = new FileDocument(DocumentName.builder(basedir).build(), file, DocumentNameMatcher.MATCHES_ALL);
+
+ File basedir = new File(tempDir.toFile(), Resources.SRC_TEST_RESOURCES);
+ basedir.mkdirs();
+ File sourceData = Resources.getExampleResource("exampleData/Source.java");
+ File file = new File(basedir, "Source.java");
+ FileUtils.copyFile(sourceData, file);
+ assertThat(file).exists();
+
+ DocumentName docName = DocumentName.builder(basedir).build();
+ document = new FileDocument(docName, file, DocumentNameMatcher.MATCHES_ALL);
}
@Test
public void reader() throws Exception {
Reader reader = document.reader();
- assertNotNull(reader, "Reader should be returned");
- assertEquals("package elements;",
- new BufferedReader(reader).readLine(), "First file line expected");
+ assertThat(reader).isNotNull();
+ assertThat(new BufferedReader(reader).readLine()).isEqualTo("package elements;");
}
@Test
public void getName() {
final DocumentName name = document.getName();
- assertNotNull(name, "Name is set");
+ assertThat(name).isNotNull();
}
}
diff --git a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
index e9a1ab8fb..d9d5a3022 100644
--- a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
+++ b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
@@ -16,18 +16,17 @@
*/
package org.apache.rat.mp;
+import static java.lang.String.format;
import static java.nio.charset.StandardCharsets.UTF_8;
import static org.apache.rat.mp.RatTestHelpers.ensureRatReportIsCorrect;
-import static org.apache.rat.mp.RatTestHelpers.getSourceDirectory;
-import static org.apache.rat.mp.RatTestHelpers.newArtifactFactory;
-import static org.apache.rat.mp.RatTestHelpers.newArtifactRepository;
-import static org.apache.rat.mp.RatTestHelpers.newSiteRenderer;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Fail.fail;
import java.io.File;
-import java.io.FileInputStream;
+import java.io.IOException;
import java.nio.file.Files;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
@@ -45,70 +44,90 @@
import org.apache.rat.license.LicenseSetFactory;
import org.apache.rat.license.LicenseSetFactory.LicenseFilter;
import org.apache.rat.report.claim.ClaimStatistic;
+import org.apache.rat.test.AbstractOptionsProvider;
+import org.apache.rat.test.utils.Resources;
import org.apache.rat.testhelpers.TextUtils;
import org.apache.rat.testhelpers.XmlUtils;
+import org.junit.jupiter.api.AfterAll;
+import org.junit.jupiter.api.Assertions;
+import org.junit.jupiter.api.Disabled;
+import org.junit.jupiter.api.Test;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
import org.w3c.dom.NamedNodeMap;
import org.w3c.dom.NodeList;
/**
* Test case for the {@link RatCheckMojo} and {@link RatReportMojo}.
*/
-public class RatCheckMojoTest extends BetterAbstractMojoTestCase {
- /**
- * Creates a new instance of {@link RatCheckMojo}.
- *
- * @param pDir The directory, where to look for a pom.xml file.
- * @return The configured Mojo.
- * @throws Exception An error occurred while creating the Mojo.
- */
- private RatCheckMojo newRatCheckMojo(String pDir) throws Exception {
- Arg.reset();
- return (RatCheckMojo) newRatMojo(pDir, "check", false);
+public class RatCheckMojoTest {
+
+ @TempDir
+ static Path tempDir;
+
+ private final static XPath xPath = XPathFactory.newInstance().newXPath();
+
+ @AfterAll
+ static void preserveData() {
+ AbstractOptionsProvider.preserveData(tempDir.toFile(), "unit");
+ }
+
+ @AfterAll
+ @EnabledOnOs(OS.WINDOWS)
+ static void cleanup() {
+ System.gc(); // hacky workaround for windows bug.
+ }
+
+ private RatCheckMojo getMojo(File pomFile) throws IOException {
+ try {
+ final RatCheckMojo mojo = new OptionMojoTest.SimpleMojoTestcase() {
+ }.getMojo(pomFile);
+ Assertions.assertNotNull(mojo);
+ return mojo;
+ } catch (IOException e) {
+ throw e;
+ } catch (Exception e) {
+ throw new IOException(format("Unable to generate mojo for %s", pomFile), e);
+ }
}
/**
* Creates a new instance of {@link AbstractRatMojo}.
*
- * @param pDir The directory, where to look for a pom.xml file.
- * @param pGoal The goal, which the Mojo must implement.
- * @param pCreateCopy if {@code true} copy the directory contents and return the
+ * @param testDir The directory, where to look for a pom.xml file.
* copy location.
* @return The configured Mojo.
* @throws Exception An error occurred while creating the Mojo.
*/
- private AbstractRatMojo newRatMojo(String pDir, String pGoal, boolean pCreateCopy) throws Exception {
- final File baseDir = new File(getBasedir());
- final File testBaseDir = getSourceDirectory(getBasedir(), pDir, pCreateCopy, baseDir);
- final File testPom = new File(testBaseDir, "pom.xml");
- final File buildDirectory = new File(new File(baseDir, "target/test"), pDir);
- AbstractRatMojo mojo = (AbstractRatMojo) lookupConfiguredMojo(testPom, pGoal);
- assertNotNull(mojo);
-
- assertNotNull("The mojo is missing its MavenProject, which will result in an NPE during RAT runs.",
- mojo.getProject());
-
- if (mojo instanceof RatReportMojo) {
- setVariableValueToObject(mojo, "localRepository", newArtifactRepository(getContainer()));
- setVariableValueToObject(mojo, "factory", newArtifactFactory());
- setVariableValueToObject(mojo, "siteRenderer", newSiteRenderer(getContainer()));
- } else if (mojo instanceof RatCheckMojo) {
- final File ratTxtFile = new File(buildDirectory, "rat.txt");
- FileUtils.write(ratTxtFile, "", UTF_8); // Ensure the output file exists and is empty (rerunning the test will append)
- mojo.setOutputFile(ratTxtFile.getAbsolutePath());
- }
+ private RatCheckMojo newRatMojo(String testDir) throws Exception {
+ Arg.reset();
+ final File sourceDir = Resources.getResourceDirectory(format("unit/%s", testDir));
+ final File baseDir = tempDir.resolve(testDir).toFile();
+ FileUtils.copyDirectory(sourceDir, baseDir);
+ final File pomFile = new File(baseDir, "pom.xml");
+ RatCheckMojo mojo = getMojo(pomFile);
+ assertThat(mojo).isNotNull();
+ assertThat(mojo.getProject())
+ .as("The mojo is missing its MavenProject, which will result in an NPE during RAT runs.")
+ .isNotNull();
+
+ File buildDirectory = new File(baseDir, "target");
+ assertThat(buildDirectory.mkdirs()).isTrue();
+ final File ratTxtFile = new File(buildDirectory, "rat.txt");
+ FileUtils.write(ratTxtFile, "", UTF_8); // Ensure the output file exists and is empty (rerunning the test will append)
+ mojo.setOutputFile(ratTxtFile.getAbsolutePath());
return mojo;
}
- private String getDir(RatCheckMojo mojo) {
- return mojo.getProject().getBasedir().getAbsolutePath().replace("\\","/") + "/";
- }
/**
* Runs a check, which should expose no problems.
*
* @throws Exception The test failed.
*/
- public void testIt1() throws Exception {
- final RatCheckMojo mojo = newRatCheckMojo("it1");
+ @Test
+ void it1() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("it1");
final File ratTxtFile = mojo.getRatTxtFile();
ReportConfiguration config = mojo.getConfiguration();
@@ -120,7 +139,7 @@ public void testIt1() throws Exception {
data.put(ClaimStatistic.Counter.APPROVED, "1");
data.put(ClaimStatistic.Counter.BINARIES, "0");
data.put(ClaimStatistic.Counter.DOCUMENT_TYPES, "2");
- data.put(ClaimStatistic.Counter.IGNORED, "1");
+ data.put(ClaimStatistic.Counter.IGNORED, "2");
data.put(ClaimStatistic.Counter.LICENSE_CATEGORIES, "1");
data.put(ClaimStatistic.Counter.LICENSE_NAMES, "1");
data.put(ClaimStatistic.Counter.NOTICES, "0");
@@ -147,8 +166,8 @@ public void testIt1() throws Exception {
private static Map mapOf(String... parts) {
Map map = new HashMap<>();
- for (int i=0; i mapOf(String... parts) {
*
* @throws Exception The test failed.
*/
- public void testIt2() throws Exception {
- final RatCheckMojo mojo = newRatCheckMojo("it2");
+ @Test
+ void it2() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("it2");
final File ratTxtFile = mojo.getRatTxtFile();
final String[] expected = {
"^Files with unapproved licenses\\s+\\*+\\s+\\Q/src.txt\\E\\s+",
@@ -167,21 +187,23 @@ public void testIt2() throws Exception {
ReporterTestUtils.counterText(ClaimStatistic.Counter.BINARIES, 0, false),
ReporterTestUtils.counterText(ClaimStatistic.Counter.ARCHIVES, 0, false),
ReporterTestUtils.counterText(ClaimStatistic.Counter.STANDARDS, 2, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 0, false),
+ ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 1, false),
ReporterTestUtils.apacheLicenseVersion2(1),
ReporterTestUtils.unknownLicense(1),
ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/src.txt") +
- ReporterTestUtils.UNKNOWN_LICENSE,
+ ReporterTestUtils.UNKNOWN_LICENSE,
ReporterTestUtils.documentOut(true, Document.Type.STANDARD, "/pom.xml") +
- ReporterTestUtils.APACHE_LICENSE
- };
+ ReporterTestUtils.APACHE_LICENSE
+ };
try {
mojo.execute();
fail("Expected RatCheckException");
} catch (RatCheckException e) {
final String msg = e.getMessage();
- assertTrue("report filename was not contained in '" + msg + "'", msg.contains(ratTxtFile.getName()));
- assertFalse("no null allowed in '" + msg + "'", (msg.toUpperCase().contains("NULL")));
+ assertThat(msg.contains(ratTxtFile.getName())).as(() -> format("report filename was not contained in '%s'", msg))
+ .isTrue();
+ assertThat(msg.toUpperCase()).contains("UNAPPROVED EXCEEDED MINIMUM");
+
ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
}
}
@@ -189,68 +211,76 @@ public void testIt2() throws Exception {
/**
* Tests adding license headers.
*/
- public void testIt3() throws Exception {
- final RatCheckMojo mojo = (RatCheckMojo) newRatMojo("it3", "check", true);
+ @Test
+ void it3() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("it3");
final File ratTxtFile = mojo.getRatTxtFile();
- final String[] expected = {
- "^Files with unapproved licenses\\s+\\*+\\s+\\Q/src.apt\\E\\s+",
- ReporterTestUtils.counterText(ClaimStatistic.Counter.NOTICES, 0, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.BINARIES, 0, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.ARCHIVES, 0, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.STANDARDS, 2, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 0, false),
- ReporterTestUtils.apacheLicenseVersion2(1),
- ReporterTestUtils.unknownLicense(1),
- ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/src.apt") +
- ReporterTestUtils.UNKNOWN_LICENSE,
- ReporterTestUtils.documentOut(true, Document.Type.STANDARD, "/pom.xml") +
- ReporterTestUtils.APACHE_LICENSE
- };
ReportConfiguration config = mojo.getConfiguration();
- assertTrue("should be adding licenses", config.isAddingLicenses());
-
+ assertThat(config.isAddingLicenses()).as("should be adding licenses").isTrue();
mojo.execute();
+ org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
- ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']", "type",
+ "STANDARD");
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src.apt']", "type",
+ "STANDARD");
+ XmlUtils.assertIsPresent(document, xPath, "/rat-report/resource[@name='/src.apt']/license[@approval='false']");
+
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src.apt']", "type",
+ "STANDARD");
+
+ for (Document.Type type : Document.Type.values()) {
+ if (type == Document.Type.STANDARD) {
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='STANDARD']", "count",
+ "2");
+ } else if (type == Document.Type.IGNORED) {
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='IGNORED']", "count",
+ "1");
+ } else {
+ XmlUtils.assertIsNotPresent(document, xPath, format("/rat-report/statistics/documentType[@name='%s']", type));
+ }
+ }
}
/**
* Tests defining licenses in configuration
*/
- public void testIt5() throws Exception {
- final RatCheckMojo mojo = (RatCheckMojo) newRatMojo("it5", "check", true);
+ @Disabled("Disabled until gitignore processing is correct")
+ @Test
+ void it5() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("it5");
final File ratTxtFile = mojo.getRatTxtFile();
ReportConfiguration config = mojo.getConfiguration();
- assertFalse("Should not be adding licenses", config.isAddingLicenses());
- assertFalse("Should not be forcing licenses", config.isAddingLicensesForced());
-
- ReportConfigurationTest.validateDefaultApprovedLicenses(config);
- assertFalse(config.getLicenseCategories(LicenseFilter.APPROVED).contains(ILicenseFamily.makeCategory("YAL")));
- ReportConfigurationTest.validateDefaultLicenseFamilies(config, "YAL");
- assertNotNull(LicenseSetFactory.familySearch("YAL", config.getLicenseFamilies(LicenseFilter.ALL)));
- ReportConfigurationTest.validateDefaultLicenses(config, "MyLicense", "CpyrT", "RegxT", "SpdxT", "TextT",
- "Not", "All", "Any");
- assertTrue(LicenseSetFactory.search("YAL", "MyLicense", config.getLicenses(LicenseFilter.ALL)).isPresent());
- try {
- mojo.execute();
- fail("Should have thrown exception");
- } catch (RatCheckException e) {
- assertThat(e.getMessage()).contains("UNAPPROVED");
- }
+ assertThat(config.isAddingLicenses()).as("Should not be adding licenses").isFalse();
+ assertThat(config.isAddingLicensesForced()).as("Should not be forcing licenses").isFalse();
+
+ ReportConfigurationTest.validateDefaultApprovedLicenses(config, 1);
+ assertThat(config.getLicenseCategories(LicenseFilter.APPROVED)).doesNotContain(ILicenseFamily.makeCategory("YAL"))
+ .contains(ILicenseFamily.makeCategory("CC"));
+ ReportConfigurationTest.validateDefaultLicenseFamilies(config, "YAL", "CC");
+ assertThat(LicenseSetFactory.familySearch("YAL", config.getLicenseFamilies(LicenseFilter.APPROVED))).isNull();
+ assertThat(LicenseSetFactory.familySearch("YAL", config.getLicenseFamilies(LicenseFilter.ALL))).isNotNull();
+ assertThat(LicenseSetFactory.familySearch("CC", config.getLicenseFamilies(LicenseFilter.APPROVED))).isNotNull();
+ assertThat(LicenseSetFactory.familySearch("CC", config.getLicenseFamilies(LicenseFilter.ALL))).isNotNull();
+
+ ReportConfigurationTest.validateDefaultLicenses(config, "CC-BY-NC-ND", "YAL");
+ assertThat(LicenseSetFactory.search("YAL", "YAL", config.getLicenses(LicenseFilter.ALL))).isPresent();
+
+ mojo.execute();
Map data = new HashMap<>();
- data.put(ClaimStatistic.Counter.APPROVED, "0");
+ data.put(ClaimStatistic.Counter.APPROVED, "1");
data.put(ClaimStatistic.Counter.ARCHIVES, "0");
data.put(ClaimStatistic.Counter.BINARIES, "0");
data.put(ClaimStatistic.Counter.DOCUMENT_TYPES, "2");
- data.put(ClaimStatistic.Counter.IGNORED, "1");
+ data.put(ClaimStatistic.Counter.IGNORED, "3");
data.put(ClaimStatistic.Counter.LICENSE_CATEGORIES, "1");
- data.put(ClaimStatistic.Counter.LICENSE_NAMES, "4");
+ data.put(ClaimStatistic.Counter.LICENSE_NAMES, "1");
data.put(ClaimStatistic.Counter.NOTICES, "0");
data.put(ClaimStatistic.Counter.STANDARDS, "1");
- data.put(ClaimStatistic.Counter.UNAPPROVED, "4");
+ data.put(ClaimStatistic.Counter.UNAPPROVED, "0");
data.put(ClaimStatistic.Counter.UNKNOWN, "0");
org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
@@ -259,35 +289,31 @@ public void testIt5() throws Exception {
for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) {
String xpath = String.format("/rat-report/statistics/statistic[@name='%s']", counter.displayName());
Map map = mapOf("approval",
- counter == ClaimStatistic.Counter.UNAPPROVED ? "false" : "true",
+ "true",
"count", data.get(counter),
"description", counter.getDescription());
XmlUtils.assertAttributes(document, xPath, xpath, map);
}
- XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/.bzrignore']",
- mapOf("mediaType", "application/octet-stream", "type", "IGNORED"));
-
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/.rat']",
+ "mediaType", "application/octet-stream", "type", "IGNORED", "isDirectory", "true");
XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']",
- mapOf("mediaType", "application/xml", "type", "STANDARD", "encoding", "ISO-8859-1"));
-
- XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']/license[@id='Any']",
- mapOf("approval", "false", "family", "YAL ", "name", "Any testing"));
- XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']/license[@id='MyLicense']",
- mapOf("approval", "false", "family", "YAL ", "name", "Yet another license"));
- XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']/license[@id='RegxT']",
- mapOf("approval", "false", "family", "YAL ", "name", "Regex with tag"));
- XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/pom.xml']/license[@id='TextT']",
- mapOf("approval", "false", "family", "YAL ", "name", "Text with tag"));
+ "mediaType", "application/xml", "type", "IGNORED", "isDirectory", "false");
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src/main/java/nl/basjes/something/Something.java']",
+ "mediaType", "text/x-java-source", "type", "STANDARD", "encoding", "ISO-8859-1");
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/src/main/java/nl/basjes/something/Something.java']/license",
+ "approval", "true", "family", ILicenseFamily.makeCategory("CC"), "id", "CC-BY-NC-ND", "name",
+ "Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International");
}
-
+
/**
* Runs a check, which should expose no problems.
*
* @throws Exception The test failed.
*/
- public void testRAT_343() throws Exception {
- final RatCheckMojo mojo = newRatCheckMojo("RAT-343");
+ @Test
+ void rat343() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("RAT-343");
final File ratTxtFile = mojo.getRatTxtFile();
// POM reports AL, BSD and CC BYas BSD because it contains the BSD and CC BY strings
final String[] expected = {
@@ -299,7 +325,7 @@ public void testRAT_343() throws Exception {
ReporterTestUtils.counterText(ClaimStatistic.Counter.BINARIES, 0, false),
ReporterTestUtils.counterText(ClaimStatistic.Counter.ARCHIVES, 0, false),
ReporterTestUtils.counterText(ClaimStatistic.Counter.STANDARDS, 1, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 0, false),
+ ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 1, false),
ReporterTestUtils.apacheLicenseVersion2(1),
"^BSD: 1 ",
"^Creative Commons Attribution: 1 ",
@@ -314,7 +340,7 @@ public void testRAT_343() throws Exception {
assertThat(config.isAddingLicensesForced()).isFalse();
assertThat(config.getCopyrightMessage()).isNull();
assertThat(config.getStyleSheet()).withFailMessage("Stylesheet should not be null").isNotNull();
-
+
ReportConfigurationTest.validateDefaultApprovedLicenses(config, 1);
ReportConfigurationTest.validateDefaultLicenseFamilies(config, "BSD", "CC BY");
ReportConfigurationTest.validateDefaultLicenses(config, "BSD", "CC BY");
@@ -326,37 +352,21 @@ public void testRAT_343() throws Exception {
/**
* Tests verifying gitignore parsing
*/
- public void /*test*/RAT_335GitIgnoreParsing() throws Exception {
- final RatCheckMojo mojo = newRatCheckMojo("RAT-335-GitIgnore");
+ @Disabled("Disabled until gitignore processing is correct")
+ @Test
+ void rat335() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("RAT-335");
final File ratTxtFile = mojo.getRatTxtFile();
-// final String[] expected = {
-// ReporterTestUtils.counterText(ClaimStatistic.Counter.NOTICES, 1, false),
-// ReporterTestUtils.counterText(ClaimStatistic.Counter.BINARIES, 0, false),
-// ReporterTestUtils.counterText(ClaimStatistic.Counter.ARCHIVES, 0, false),
-// ReporterTestUtils.counterText(ClaimStatistic.Counter.STANDARDS, 6, false),
-// ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 0, false),
-// ReporterTestUtils.counterText(ClaimStatistic.Counter.UNKNOWN, 4, false),
-// ReporterTestUtils.apacheLicenseVersion2(2),
-// ReporterTestUtils.unknownLicense(4),
-// ReporterTestUtils.documentOut(true, Document.Type.STANDARD, "/pom.xml") +
-// ReporterTestUtils.APACHE_LICENSE,
-// ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/dir1/dir1.md") +
-// ReporterTestUtils.UNKNOWN_LICENSE,
-// ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/dir2/dir2.txt") +
-// ReporterTestUtils.UNKNOWN_LICENSE,
-// ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/dir3/file3.log") +
-// ReporterTestUtils.UNKNOWN_LICENSE,
-// };
try {
mojo.execute();
fail("Expected RatCheckException");
} catch (RatCheckException e) {
final String msg = e.getMessage();
- assertTrue("report filename was not contained in '" + msg + "'", msg.contains(ratTxtFile.getName()));
- assertFalse("no null allowed in '" + msg + "'", (msg.toUpperCase().contains("NULL")));
+ assertThat(msg).contains(ratTxtFile.getName());
+ assertThat(msg).contains("UNAPPROVED exceeded minimum");
Map data = new HashMap<>();
- data.put(ClaimStatistic.Counter.APPROVED, "2");
+ data.put(ClaimStatistic.Counter.APPROVED, "1");
data.put(ClaimStatistic.Counter.ARCHIVES, "0");
data.put(ClaimStatistic.Counter.BINARIES, "0");
data.put(ClaimStatistic.Counter.DOCUMENT_TYPES, "3");
@@ -364,12 +374,11 @@ public void testRAT_343() throws Exception {
data.put(ClaimStatistic.Counter.LICENSE_CATEGORIES, "2");
data.put(ClaimStatistic.Counter.LICENSE_NAMES, "2");
data.put(ClaimStatistic.Counter.NOTICES, "1");
- data.put(ClaimStatistic.Counter.STANDARDS, "6");
+ data.put(ClaimStatistic.Counter.STANDARDS, "5");
data.put(ClaimStatistic.Counter.UNAPPROVED, "4");
data.put(ClaimStatistic.Counter.UNKNOWN, "4");
org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
- XPath xPath = XPathFactory.newInstance().newXPath();
for (ClaimStatistic.Counter counter : ClaimStatistic.Counter.values()) {
String xpath = String.format("/rat-report/statistics/statistic[@name='%s']", counter.displayName());
@@ -382,31 +391,30 @@ public void testRAT_343() throws Exception {
// license categories
XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseCategory[@name='?????']",
- mapOf("count", "4" ));
+ mapOf("count", "4"));
XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseCategory[@name='AL ']",
- mapOf("count", "2" ));
+ mapOf("count", "1"));
// license names
XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseName[@name='Apache License Version 2.0']",
- mapOf("count", "2" ));
+ mapOf("count", "1"));
XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/licenseName[@name='Unknown license']",
- mapOf("count", "4" ));
+ mapOf("count", "4"));
// Document types
XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='IGNORED']",
- mapOf("count", "6" ));
+ mapOf("count", "6"));
XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='NOTICE']",
- mapOf("count", "1" ));
+ mapOf("count", "1"));
XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='STANDARD']",
- mapOf("count", "6" ));
+ mapOf("count", "5"));
List ignoredFiles = new ArrayList<>(Arrays.asList(
"/dir1/dir1.txt",
- "/dir1/file1.log",
"/dir1/.gitignore",
"/dir2/dir2.md",
"/dir3/dir3.log",
@@ -414,7 +422,7 @@ public void testRAT_343() throws Exception {
"/root.md"));
NodeList nodeList = XmlUtils.getNodeList(document, xPath, "/rat-report/resource[@type='IGNORED']");
- for (int i=0;i< nodeList.getLength(); i++) {
+ for (int i = 0; i < nodeList.getLength(); i++) {
NamedNodeMap attr = nodeList.item(i).getAttributes();
String s = attr.getNamedItem("name").getNodeValue();
assertThat(ignoredFiles).contains(s);
@@ -431,62 +439,46 @@ public void testRAT_343() throws Exception {
* So for this test we must create such a file which is specific for the current
* working directory.
*/
- public void /*test*/RAT362GitIgnore() throws Exception {
- final RatCheckMojo mojo = newRatCheckMojo("RAT-362-GitIgnore");
+ @Disabled("Disabled until gitignore processing is correct")
+ @Test
+ void rat362() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("RAT-362");
final File ratTxtFile = mojo.getRatTxtFile();
- final String dirStr = getDir(mojo);
-
- if (dirStr.contains(":")) {
- // The problem this is testing for cannot happen if there is
- // a Windows drive letter in the name of the directory.
- // Any duplication of a ':' will make it all fail always.
- // So there is no point in continuing this test.
- return;
- }
- File dir = new File(dirStr);
-
- // Make the target directory for the test file
- assertTrue(dir.isDirectory());
-
- // Create the test file with a content on which it must fail
- File barFile = new File(dir, "bar.md");
- assertThat(barFile).exists();
- final String[] expected = {
- ReporterTestUtils.counterText(ClaimStatistic.Counter.NOTICES, 0, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.BINARIES, 0, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.ARCHIVES, 0, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.STANDARDS, 3, false),
- ReporterTestUtils.counterText(ClaimStatistic.Counter.IGNORED, 0, false),
- ReporterTestUtils.apacheLicenseVersion2(2),
- ReporterTestUtils.unknownLicense(1),
- ReporterTestUtils.documentOut(false, Document.Type.STANDARD, "/bar.md") +
- ReporterTestUtils.UNKNOWN_LICENSE
- };
try {
mojo.execute();
- fail("Expected RatCheckException: This check should have failed on the invalid test file");
+ fail("Expected RatCheckException");
} catch (RatCheckException e) {
final String msg = e.getMessage();
- assertTrue("report filename was not contained in '" + msg + "'", msg.contains(ratTxtFile.getName()));
- assertFalse("no null allowed in '" + msg + "'", (msg.toUpperCase().contains("NULL")));
- ensureRatReportIsCorrect(ratTxtFile, expected, TextUtils.EMPTY);
+ assertThat(msg).contains(ratTxtFile.getName());
+ assertThat(msg).contains("UNAPPROVED exceeded minimum");
+
+ org.w3c.dom.Document document = XmlUtils.toDom(Files.newInputStream(ratTxtFile.toPath()));
+ // Document types
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/statistics/documentType[@name='IGNORED']",
+ "count", "3");
+
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/bar.md']",
+ "type", "STANDARD");
+ XmlUtils.assertAttributes(document, xPath, "/rat-report/resource[@name='/foo.md']",
+ "type", "IGNORED");
}
}
/**
- * Tests implicit excludes apply to submodules too
- */
- public void testRAT_107() throws Exception {
- final RatCheckMojo mojo = (RatCheckMojo) newRatMojo("RAT-107", "check", true);
- final File ratTxtFile = mojo.getRatTxtFile();
- final String[] expected = {};
- final String[] notExpected = {};
- setVariableValueToObject(mojo, "excludeSubProjects", Boolean.FALSE);
- mojo.setInputExcludeParsedScm("MAVEN");
- mojo.setInputExcludeParsedScm("idea");
- mojo.setInputExcludeParsedScm("eclipse");
- mojo.execute();
-
- ensureRatReportIsCorrect(ratTxtFile, expected, notExpected);
- }
+ * Tests implicit excludes apply to submodules too
+ */
+ @Test
+ void rat107() throws Exception {
+ final RatCheckMojo mojo = newRatMojo("RAT-107");
+ final File ratTxtFile = mojo.getRatTxtFile();
+ final String[] expected = {};
+ final String[] notExpected = {};
+ //setVariableValueToObject(mojo, "excludeSubProjects", Boolean.FALSE);
+ mojo.setInputExcludeParsedScm("MAVEN");
+ mojo.setInputExcludeParsedScm("idea");
+ mojo.setInputExcludeParsedScm("eclipse");
+ mojo.execute();
+
+ ensureRatReportIsCorrect(ratTxtFile, expected, notExpected);
+ }
}
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore
deleted file mode 100644
index 8855fa805..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/.gitignore
+++ /dev/null
@@ -1,7 +0,0 @@
-*.md
-
-# This makes it ignore dir3/dir3.log and dir3/file3.log
-*.log
-
-# This makes it "unignore" dir3/file3.log
-!file*.log
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore
deleted file mode 100644
index 26fd5c956..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/.gitignore
+++ /dev/null
@@ -1,3 +0,0 @@
-*.txt
-!dir1.md
-file1.log
\ No newline at end of file
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.txt b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.txt
deleted file mode 100644
index a31cbc897..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.txt
+++ /dev/null
@@ -1 +0,0 @@
-File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/file1.log b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/file1.log
deleted file mode 100644
index a31cbc897..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/file1.log
+++ /dev/null
@@ -1 +0,0 @@
-File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.md b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.md
deleted file mode 100644
index a31cbc897..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.md
+++ /dev/null
@@ -1 +0,0 @@
-File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/dir3.log b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/dir3.log
deleted file mode 100644
index a31cbc897..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/dir3.log
+++ /dev/null
@@ -1 +0,0 @@
-File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/root.md b/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/root.md
deleted file mode 100644
index a31cbc897..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/root.md
+++ /dev/null
@@ -1 +0,0 @@
-File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/README.txt b/apache-rat-plugin/src/test/resources/unit/RAT-335/README.txt
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/README.txt
rename to apache-rat-plugin/src/test/resources/unit/RAT-335/README.txt
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.md b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/dir1.md
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir1/dir1.md
rename to apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/dir1.md
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.txt b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir2/dir2.txt
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir2/dir2.txt
rename to apache-rat-plugin/src/test/resources/unit/RAT-335/dir2/dir2.txt
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/file3.log b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir3/file3.log
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/dir3/file3.log
rename to apache-rat-plugin/src/test/resources/unit/RAT-335/dir3/file3.log
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/invoker.properties b/apache-rat-plugin/src/test/resources/unit/RAT-335/invoker.properties
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/invoker.properties
rename to apache-rat-plugin/src/test/resources/unit/RAT-335/invoker.properties
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/pom.xml b/apache-rat-plugin/src/test/resources/unit/RAT-335/pom.xml
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-335-GitIgnore/pom.xml
rename to apache-rat-plugin/src/test/resources/unit/RAT-335/pom.xml
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/.gitignore
deleted file mode 100644
index 4912996bc..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/.gitignore
+++ /dev/null
@@ -1,2 +0,0 @@
-/foo.md
-target
\ No newline at end of file
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/foo.md b/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/foo.md
deleted file mode 100644
index a31cbc897..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/foo.md
+++ /dev/null
@@ -1 +0,0 @@
-File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/bar.md b/apache-rat-plugin/src/test/resources/unit/RAT-362/bar.md
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/bar.md
rename to apache-rat-plugin/src/test/resources/unit/RAT-362/bar.md
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/invoker.properties b/apache-rat-plugin/src/test/resources/unit/RAT-362/invoker.properties
similarity index 100%
rename from apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/invoker.properties
rename to apache-rat-plugin/src/test/resources/unit/RAT-362/invoker.properties
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/pom.xml b/apache-rat-plugin/src/test/resources/unit/RAT-362/pom.xml
similarity index 97%
rename from apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/pom.xml
rename to apache-rat-plugin/src/test/resources/unit/RAT-362/pom.xml
index 71669aa32..af34ad819 100644
--- a/apache-rat-plugin/src/test/resources/unit/RAT-362-GitIgnore/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-362/pom.xml
@@ -27,6 +27,7 @@
apache-rat-plugin@pom.version@
+ xml**/.gitignore
diff --git a/apache-rat-plugin/src/test/resources/unit/it3/pom.xml b/apache-rat-plugin/src/test/resources/unit/it3/pom.xml
index f6982e399..1188a2d28 100644
--- a/apache-rat-plugin/src/test/resources/unit/it3/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/it3/pom.xml
@@ -29,6 +29,7 @@
1true
+ xml
From 57098407bb55e1c040afdd6d3d1fa855800ae9aa Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Fri, 7 Feb 2025 09:22:47 +0100
Subject: [PATCH 33/41] RAT-98: Improve logging messages (#436)
* initial changes
* Remove unthrown exception
* Changed to StringBuilder
---------
Co-authored-by: P. Ottlinger
---
.../configuration/XMLConfigurationReader.java | 161 +++++++++++-------
.../rat/report/xml/writer/XmlWriter.java | 4 +-
.../main/java/org/apache/rat/utils/Log.java | 17 +-
3 files changed, 116 insertions(+), 66 deletions(-)
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 0bf2dda8d..e92a2baf6 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
@@ -126,6 +126,21 @@ public SortedSet licenseFamilies() {
};
}
+ /**
+ * Creates textual representation of a node for display.
+ * @param node the node to create the textual representation of.
+ * @return The textual representation of the node for display.
+ */
+ private String nodeText(final Node node) {
+ StringBuilder stringBuilder = new StringBuilder().append("<").append(node.getNodeName());
+ NamedNodeMap attr = node.getAttributes();
+ for (int i = 0; i < attr.getLength(); i++) {
+ Node n = attr.item(i);
+ stringBuilder.append(String.format(" %s='%s'", n.getNodeName(), n.getNodeValue()));
+ }
+ return stringBuilder.append(">").toString();
+ }
+
@Override
public void addLicenses(final URI uri) {
read(uri);
@@ -327,22 +342,27 @@ private void setValue(final Description description, final Description childDesc
*/
private Pair> processChildNodes(final Description description, final Node parent,
final BiPredicate childProcessor) {
- boolean foundChildren = false;
- List children = new ArrayList<>();
- // check XML child nodes.
- if (parent.hasChildNodes()) {
-
- nodeListConsumer(parent.getChildNodes(), n -> {
- if (n.getNodeType() == Node.ELEMENT_NODE) {
- children.add(n);
+ try {
+ boolean foundChildren = false;
+ List children = new ArrayList<>();
+ // check XML child nodes.
+ if (parent.hasChildNodes()) {
+
+ nodeListConsumer(parent.getChildNodes(), n -> {
+ if (n.getNodeType() == Node.ELEMENT_NODE) {
+ children.add(n);
+ }
+ });
+ foundChildren = !children.isEmpty();
+ if (foundChildren) {
+ processChildren(description, children, childProcessor);
}
- });
- foundChildren = !children.isEmpty();
- if (foundChildren) {
- processChildren(description, children, childProcessor);
}
+ return new ImmutablePair<>(foundChildren, children);
+ } catch (RuntimeException exception) {
+ DefaultLog.getInstance().error(String.format("Child node extraction error in: '%s'", nodeText(parent)));
+ throw exception;
}
- return new ImmutablePair<>(foundChildren, children);
}
/**
@@ -408,6 +428,7 @@ private AbstractBuilder parseMatcher(final Node matcherNode) {
}
} catch (DOMException e) {
+ DefaultLog.getInstance().error(String.format("Matcher error in: '%s'", nodeText(matcherNode)));
throw new ConfigurationException(e);
}
return builder.hasId() ? new IDRecordingBuilder(matchers, builder) : builder;
@@ -445,34 +466,39 @@ private BiPredicate licenseChildNodeProcessor(final ILicense.
* @return the License definition.
*/
private ILicense parseLicense(final Node licenseNode) {
- ILicense.Builder builder = ILicense.builder();
- // get the description for the builder
- Description description = builder.getDescription();
- // set the BUILDER_PARAM options from the description
- processBuilderParams(description, builder);
- // set the children from attributes.
- description.setChildren(builder, attributes(licenseNode));
- // set children from the child nodes
- Pair> pair = processChildNodes(description, licenseNode,
- licenseChildNodeProcessor(builder, description));
- List children = pair.getRight();
-
- // check for inline nodes that can accept child nodes.
- List childDescriptions = description.getChildren().values().stream()
- .filter(d -> XMLConfig.isLicenseInline(d.getCommonName())).collect(Collectors.toList());
- for (Description childDescription : childDescriptions) {
- Iterator iter = children.iterator();
- while (iter.hasNext()) {
- callSetter(childDescription, builder, parseMatcher(iter.next()));
- iter.remove();
+ try {
+ ILicense.Builder builder = ILicense.builder();
+ // get the description for the builder
+ Description description = builder.getDescription();
+ // set the BUILDER_PARAM options from the description
+ processBuilderParams(description, builder);
+ // set the children from attributes.
+ description.setChildren(builder, attributes(licenseNode));
+ // set children from the child nodes
+ Pair> pair = processChildNodes(description, licenseNode,
+ licenseChildNodeProcessor(builder, description));
+ List children = pair.getRight();
+
+ // check for inline nodes that can accept child nodes.
+ List childDescriptions = description.getChildren().values().stream()
+ .filter(d -> XMLConfig.isLicenseInline(d.getCommonName())).collect(Collectors.toList());
+ for (Description childDescription : childDescriptions) {
+ Iterator iter = children.iterator();
+ while (iter.hasNext()) {
+ callSetter(childDescription, builder, parseMatcher(iter.next()));
+ iter.remove();
+ }
}
- }
- if (!children.isEmpty()) {
- children.forEach(n -> DefaultLog.getInstance().warn(String.format("unrecognised child node '%s' in node '%s'%n",
- n.getNodeName(), licenseNode.getNodeName())));
+ if (!children.isEmpty()) {
+ children.forEach(n -> DefaultLog.getInstance().warn(String.format("unrecognised child node '%s' in node '%s'%n",
+ n.getNodeName(), licenseNode.getNodeName())));
+ }
+ return builder.build();
+ } catch (RuntimeException exception) {
+ DefaultLog.getInstance().error(String.format("License error in: '%s'", nodeText(licenseNode)));
+ throw exception;
}
- return builder.build();
}
@Override
@@ -519,12 +545,17 @@ private ILicenseFamily parseFamily(final Map attributes) {
*/
private void parseFamily(final Node familyNode) {
if (XMLConfig.FAMILY.equals(familyNode.getNodeName())) {
- ILicenseFamily result = parseFamily(attributes(familyNode));
- if (result == null) {
- throw new ConfigurationException(
- String.format("families/family tag requires %s attribute", XMLConfig.ATT_ID));
+ try {
+ ILicenseFamily result = parseFamily(attributes(familyNode));
+ if (result == null) {
+ throw new ConfigurationException(
+ String.format("families/family tag requires %s attribute", XMLConfig.ATT_ID));
+ }
+ licenseFamilies.add(result);
+ } catch (RuntimeException exception) {
+ DefaultLog.getInstance().error(String.format("Family error in: '%s'", nodeText(familyNode)));
+ throw exception;
}
- licenseFamilies.add(result);
}
}
@@ -535,21 +566,26 @@ private void parseFamily(final Node familyNode) {
*/
private void parseApproved(final Node approvedNode) {
if (XMLConfig.FAMILY.equals(approvedNode.getNodeName())) {
- Map attributes = attributes(approvedNode);
- if (attributes.containsKey(XMLConfig.ATT_LICENSE_REF)) {
- approvedFamilies.add(attributes.get(XMLConfig.ATT_LICENSE_REF));
- } else if (attributes.containsKey(XMLConfig.ATT_ID)) {
- ILicenseFamily target = parseFamily(attributes);
- if (target != null) {
- licenseFamilies.add(target);
- String familyCategory = target.getFamilyCategory();
- if (StringUtils.isNotBlank(familyCategory)) {
- approvedFamilies.add(familyCategory);
+ try {
+ Map attributes = attributes(approvedNode);
+ if (attributes.containsKey(XMLConfig.ATT_LICENSE_REF)) {
+ approvedFamilies.add(attributes.get(XMLConfig.ATT_LICENSE_REF));
+ } else if (attributes.containsKey(XMLConfig.ATT_ID)) {
+ ILicenseFamily target = parseFamily(attributes);
+ if (target != null) {
+ licenseFamilies.add(target);
+ String familyCategory = target.getFamilyCategory();
+ if (StringUtils.isNotBlank(familyCategory)) {
+ approvedFamilies.add(familyCategory);
+ }
}
+ } else {
+ throw new ConfigurationException(String.format("family tag requires %s or %s attribute",
+ XMLConfig.ATT_LICENSE_REF, XMLConfig.ATT_ID));
}
- } else {
- throw new ConfigurationException(String.format("family tag requires %s or %s attribute",
- XMLConfig.ATT_LICENSE_REF, XMLConfig.ATT_ID));
+ } catch (RuntimeException exception) {
+ DefaultLog.getInstance().error(String.format("Approved error in: '%s'", nodeText(approvedNode)));
+ throw exception;
}
}
}
@@ -569,11 +605,16 @@ public SortedSet approvedLicenseId() {
}
private void parseMatcherBuilder(final Node classNode) {
- Map attributes = attributes(classNode);
- if (attributes.get(XMLConfig.ATT_CLASS_NAME) == null) {
- throw new ConfigurationException("matcher must have a " + XMLConfig.ATT_CLASS_NAME + " attribute");
+ try {
+ Map attributes = attributes(classNode);
+ if (attributes.get(XMLConfig.ATT_CLASS_NAME) == null) {
+ throw new ConfigurationException("matcher must have a " + XMLConfig.ATT_CLASS_NAME + " attribute");
+ }
+ MatcherBuilderTracker.addBuilder(attributes.get(XMLConfig.ATT_CLASS_NAME), attributes.get(XMLConfig.ATT_NAME));
+ } catch (RuntimeException exception) {
+ DefaultLog.getInstance().error(String.format("Matcher error in: '%s'", nodeText(classNode)));
+ throw exception;
}
- MatcherBuilderTracker.addBuilder(attributes.get(XMLConfig.ATT_CLASS_NAME), attributes.get(XMLConfig.ATT_NAME));
}
@Override
diff --git a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java
index 53a0dfb61..128f32f6f 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/report/xml/writer/XmlWriter.java
@@ -482,7 +482,7 @@ public IXmlWriter comment(final CharSequence text) throws IOException {
/**
* Writes an attribute of an element. Note that this is only allowed directly
- * after {@link #openElement(CharSequence)} or {@link #attribute}.
+ * after {@link #openElement(CharSequence)} or a previous {@code attribute} call.
*
* @param name the attribute name, not null
* @param value the attribute value, not null
@@ -717,7 +717,7 @@ private boolean isValidNameBody(final char character) {
}
@Override
- public void close() throws Exception {
+ public void close() throws IOException {
closeDocument();
}
}
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 d12db3e6c..624cb7394 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
@@ -18,7 +18,6 @@
*/
package org.apache.rat.utils;
-import java.io.IOException;
import java.io.PrintWriter;
import java.io.StringWriter;
import java.io.Writer;
@@ -184,6 +183,15 @@ default void error(Object message, Throwable throwable) {
* @return the Writer backed by this log.
*/
default Writer asWriter() {
+ return asWriter(Level.INFO);
+ }
+
+ /**
+ * Returns a Writer backed by this log. All messages are logged at "INFO" level.
+ * @return the Writer backed by this log.
+ * @param level the Log level to write at.
+ */
+ default Writer asWriter(Level level) {
return new Writer() {
private StringBuilder sb = new StringBuilder();
@@ -195,7 +203,7 @@ public void write(final char[] cbuf, final int off, final int len) {
sb.append(txt);
} else {
while (pos > -1) {
- Log.this.info(sb.append(txt, 0, pos).toString());
+ Log.this.log(level, sb.append(txt, 0, pos).toString());
sb.delete(0, sb.length());
txt = txt.substring(pos + 1);
pos = txt.indexOf(System.lineSeparator());
@@ -207,15 +215,16 @@ public void write(final char[] cbuf, final int off, final int len) {
@Override
public void flush() {
if (sb.length() > 0) {
- Log.this.info(sb.toString());
+ Log.this.log(level, sb.toString());
}
sb = new StringBuilder();
}
@Override
- public void close() throws IOException {
+ public void close() {
flush();
}
};
}
+
}
From 08d671640d3cf40de34942438fc6537bb8e2d927 Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Fri, 7 Feb 2025 18:44:47 +0100
Subject: [PATCH 34/41] RAT-98: Converted to FileProcessorBuilder design
(#439)
* Converted to FileProcessorBuilder design
* Minor changes during review
* removed unused method
---------
Co-authored-by: P. Ottlinger
---
.../config/exclusion/ExclusionProcessor.java | 15 +-
.../config/exclusion/StandardCollection.java | 37 +--
.../AbstractFileProcessorBuilder.java | 232 ++++++++++++++++++
...rocessor.java => BazaarIgnoreBuilder.java} | 16 +-
...leProcessor.java => CVSIgnoreBuilder.java} | 24 +-
.../DescendingFileProcessor.java | 121 ---------
.../fileProcessors/GitFileProcessor.java | 70 ------
.../fileProcessors/GitIgnoreBuilder.java | 105 ++++++++
...oreProcessor.java => HgIgnoreBuilder.java} | 34 ++-
.../main/java/org/apache/rat/help/Help.java | 2 +-
.../exclusion/StandardCollectionTest.java | 2 +-
.../AbstractIgnoreBuilderTest.java | 118 +++++++++
.../AbstractIgnoreProcessorTest.java | 62 -----
.../BazaarIgnoreBuilderTest.java | 43 ++++
...sorTest.java => CVSIgnoreBuilderTest.java} | 21 +-
.../DescendingFileProcessorTest.java | 70 ------
.../fileProcessors/GitFileProcessorTest.java | 118 ---------
.../fileProcessors/GitIgnoreBuilderTest.java | 138 +++++++++++
...ssorTest.java => HgIgnoreBuilderTest.java} | 32 +--
.../commandLine.txt | 0
.../expected-message.txt | 0
.../{RAT_355 => GitIgnoreBuilderTest}/pom.xml | 0
.../GitIgnoreBuilderTest/src/.gitignore | 7 +
.../src/README.txt | 0
.../GitIgnoreBuilderTest/src/dir1/.gitignore | 3 +
.../src/dir1/dir1.md | 0
.../src/dir1/dir1.txt} | 0
.../src/dir1/file1.log} | 0
.../GitIgnoreBuilderTest/src/dir2/dir2.md | 1 +
.../GitIgnoreBuilderTest/src/dir2/dir2.txt | 1 +
.../GitIgnoreBuilderTest/src/dir3/dir3.log | 1 +
.../GitIgnoreBuilderTest/src/dir3/file3.log | 1 +
.../src/invoker.properties | 0
.../GitIgnoreBuilderTest/src/root.md | 1 +
.../verify.groovy | 0
35 files changed, 745 insertions(+), 530 deletions(-)
create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/AbstractFileProcessorBuilder.java
rename apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/{BazaarIgnoreProcessor.java => BazaarIgnoreBuilder.java} (71%)
rename apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/{CVSFileProcessor.java => CVSIgnoreBuilder.java} (63%)
delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessor.java
delete mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessor.java
create mode 100644 apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilder.java
rename apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/{HgIgnoreProcessor.java => HgIgnoreBuilder.java} (59%)
create mode 100644 apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreBuilderTest.java
delete mode 100644 apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreProcessorTest.java
create mode 100644 apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilderTest.java
rename apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/{CVSFileProcessorTest.java => CVSIgnoreBuilderTest.java} (65%)
delete mode 100644 apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessorTest.java
delete mode 100644 apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessorTest.java
create mode 100644 apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilderTest.java
rename apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/{HgIgnoreProcessorTest.java => HgIgnoreBuilderTest.java} (53%)
rename apache-rat-core/src/test/resources/{RAT_355 => GitIgnoreBuilderTest}/commandLine.txt (100%)
rename apache-rat-core/src/test/resources/{RAT_355 => GitIgnoreBuilderTest}/expected-message.txt (100%)
rename apache-rat-core/src/test/resources/{RAT_355 => GitIgnoreBuilderTest}/pom.xml (100%)
create mode 100644 apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/.gitignore
rename apache-rat-core/src/test/resources/{RAT_355 => GitIgnoreBuilderTest}/src/README.txt (100%)
create mode 100644 apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/.gitignore
rename apache-rat-core/src/test/resources/{RAT_355 => GitIgnoreBuilderTest}/src/dir1/dir1.md (100%)
rename apache-rat-core/src/test/resources/{RAT_355/src/dir2/dir2.txt => GitIgnoreBuilderTest/src/dir1/dir1.txt} (100%)
rename apache-rat-core/src/test/resources/{RAT_355/src/dir3/file3.log => GitIgnoreBuilderTest/src/dir1/file1.log} (100%)
create mode 100644 apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.md
create mode 100644 apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.txt
create mode 100644 apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/dir3.log
create mode 100644 apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/file3.log
rename apache-rat-core/src/test/resources/{RAT_355 => GitIgnoreBuilderTest}/src/invoker.properties (100%)
create mode 100644 apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/root.md
rename apache-rat-core/src/test/resources/{RAT_355 => GitIgnoreBuilderTest}/verify.groovy (100%)
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
index d5b3ebe4b..7f9087500 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/ExclusionProcessor.java
@@ -209,15 +209,12 @@ public DocumentNameMatcher getNameMatcher(final DocumentName basedir) {
private List extractFileProcessors(final DocumentName basedir) {
final List fileProcessorList = new ArrayList<>();
for (StandardCollection sc : fileProcessors) {
- final Set names = new HashSet<>();
- sc.fileProcessor().map(fp -> fp.apply(basedir)).forEachRemaining(n -> n.forEach(names::add));
- MatcherSet.Builder builder = new MatcherSet.Builder();
- Set matching = new HashSet<>();
- Set notMatching = new HashSet<>();
- MatcherSet.Builder.segregateList(matching, notMatching, names);
- builder.addIncluded(basedir.resolve(sc.name()), notMatching);
- builder.addExcluded(basedir.resolve(sc.name()), matching);
- fileProcessorList.add(builder.build());
+ ExtendedIterator> iter = sc.fileProcessorBuilder().map(builder -> builder.build(basedir));
+ if (iter.hasNext()) {
+ iter.forEachRemaining(fileProcessorList::addAll);
+ } else {
+ DefaultLog.getInstance().debug(String.format("%s does not have a fileProcessor.", sc));
+ }
}
return fileProcessorList;
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
index d2c59707c..62c179725 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/StandardCollection.java
@@ -28,10 +28,11 @@
import java.util.Set;
import java.util.function.Predicate;
-import org.apache.rat.config.exclusion.fileProcessors.BazaarIgnoreProcessor;
-import org.apache.rat.config.exclusion.fileProcessors.CVSFileProcessor;
-import org.apache.rat.config.exclusion.fileProcessors.GitFileProcessor;
-import org.apache.rat.config.exclusion.fileProcessors.HgIgnoreProcessor;
+import org.apache.rat.config.exclusion.fileProcessors.AbstractFileProcessorBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.BazaarIgnoreBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.CVSIgnoreBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.GitIgnoreBuilder;
+import org.apache.rat.config.exclusion.fileProcessors.HgIgnoreBuilder;
import org.apache.rat.document.DocumentName;
import org.apache.rat.document.DocumentNameMatcher;
import org.apache.rat.utils.ExtendedIterator;
@@ -55,7 +56,7 @@ public enum StandardCollection {
* The files and directories created by a Bazaar source code control based tool.
*/
BAZAAR("The files and directories created by a Bazaar source code control based tool.",
- Arrays.asList("**/.bzr/**", "**/.bzrignore"), null, new BazaarIgnoreProcessor()),
+ Arrays.asList("**/.bzr/**", "**/.bzrignore"), null, new BazaarIgnoreBuilder()),
/**
* The files and directories created by a Bitkeeper source code control based tool.
*/
@@ -74,7 +75,7 @@ public enum StandardCollection {
"**/*.orig", "**/*.rej", "**/.del-*",
"**/*.a", "**/*.old", "**/*.o", "**/*.obj", "**/*.so", "**/*.exe",
"**/*.Z", "**/*.elc", "**/*.ln", "**/core"),
- null, new CVSFileProcessor()),
+ null, new CVSIgnoreBuilder()),
/**
* The files and directories created by a DARCS source code control based tool.
*/
@@ -93,7 +94,7 @@ null, new CVSFileProcessor()),
GIT("The files and directories created by GIT source code control to support GIT, also processes files listed in '.gitignore'.",
Arrays.asList("**/.git/**", "**/.gitignore"),
null,
- new GitFileProcessor()
+ new GitIgnoreBuilder()
),
/**
* The hidden directories. Directories with names that start with {@code .}
@@ -135,9 +136,9 @@ public String toString() {
IDEA("The files and directories created by an IDEA IDE based tool.",
Arrays.asList("**/*.iml", "**/*.ipr", "**/*.iws", "**/.idea/**"), null, null),
/**
- * The .DS_Store files on Mac computers.
+ * The {@code .DS_Store} files on Mac computers.
*/
- MAC("The .DS_Store files Mac computers.",
+ MAC("The .DS_Store files on Mac computers.",
Collections.singletonList("**/.DS_Store"), null, null),
/**
* The files and directories created by Maven build system based project.
@@ -156,7 +157,7 @@ public String toString() {
* The files and directories created by a Mercurial source code control based tool.
*/
MERCURIAL("The files and directories created by a Mercurial source code control based tool.",
- Arrays.asList("**/.hg/**", "**/.hgignore"), null, new HgIgnoreProcessor()),
+ Arrays.asList("**/.hg/**", "**/.hgignore"), null, new HgIgnoreBuilder()),
/**
* The set of miscellaneous files generally left by editors and the like.
*/
@@ -213,17 +214,17 @@ public String toString() {
private final Collection patterns;
/** A document name matcher supplier to create a document name matcher. May be null */
private final DocumentNameMatcher staticDocumentNameMatcher;
- /** The FileProcessor to process the exclude file associated with this exclusion. May be null. */
- private final FileProcessor fileProcessor;
+ /** The AbstractFileProcessorBuilder to process the exclude file associated with this exclusion. May be {@code null}. */
+ private final AbstractFileProcessorBuilder fileProcessorBuilder;
/** The description of this collection */
private final String desc;
StandardCollection(final String desc, final Collection patterns, final DocumentNameMatcher documentNameMatcher,
- final FileProcessor fileProcessor) {
+ final AbstractFileProcessorBuilder fileProcessorBuilder) {
this.desc = desc;
this.patterns = patterns == null ? Collections.emptyList() : new HashSet<>(patterns);
this.staticDocumentNameMatcher = documentNameMatcher;
- this.fileProcessor = fileProcessor;
+ this.fileProcessorBuilder = fileProcessorBuilder;
}
/**
@@ -277,11 +278,11 @@ public Set patterns() {
*
* @return the fileProcessor if it exists, {@code null} otherwise.
*/
- public ExtendedIterator fileProcessor() {
- List lst = new ArrayList<>();
+ public ExtendedIterator fileProcessorBuilder() {
+ List lst = new ArrayList<>();
for (StandardCollection sc : getCollections()) {
- if (sc.fileProcessor != null) {
- lst.add(sc.fileProcessor);
+ if (sc.fileProcessorBuilder != null) {
+ lst.add(sc.fileProcessorBuilder);
}
}
return ExtendedIterator.create(lst.iterator());
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/AbstractFileProcessorBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/AbstractFileProcessorBuilder.java
new file mode 100644
index 000000000..9e33aeabb
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/AbstractFileProcessorBuilder.java
@@ -0,0 +1,232 @@
+/*
+ * 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.exclusion.fileProcessors;
+
+import java.io.File;
+import java.io.FileFilter;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Objects;
+import java.util.Optional;
+import java.util.Set;
+import java.util.SortedMap;
+import java.util.TreeMap;
+import java.util.function.Consumer;
+import java.util.function.Predicate;
+import java.util.stream.Collectors;
+
+import org.apache.commons.io.filefilter.DirectoryFileFilter;
+import org.apache.commons.io.filefilter.NameFileFilter;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.rat.config.exclusion.ExclusionUtils;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.config.exclusion.plexus.MatchPattern;
+import org.apache.rat.config.exclusion.plexus.MatchPatterns;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+
+/**
+ * Creates a List of {@link MatcherSet}s that represent the inclusions and exclusions of this file processor.
+ *
+ * By default this processor:
+ *
+ *
+ *
Creates a list of levels that correspond to the depth of the directories where the specific include/exclude file is located.
+ * Directory depth is relative to the initially discovered include/exclude file.
+ *
A MatcherSet is created for each include/exclude file located, and the MatcherSet is added to the proper level.
+ *
During the build:
+ *
+ *
Each level creates a MatcherSet for the level.
+ *
The MatcherSet for each level is returned in reverse order (deepest first). This ensures that most include/exclude
+ * files will be properly handled.
+ *
+ *
+ */
+public abstract class AbstractFileProcessorBuilder {
+ /** A String format pattern to print a regex string */
+ protected static final String REGEX_FMT = "%%regex[%s]";
+ /** The name of the file being processed */
+ protected final String fileName;
+ /** The predicate that will return {@code false} for any comment line in the file. */
+ protected final Predicate commentFilter;
+ /** the collection of level builders */
+ private final SortedMap levelBuilders;
+ /** If {@code true} then the processor file name will be included in the list of files to ignore */
+ private final boolean includeProcessorFile;
+
+ /**
+ * Constructor for multiple comment prefixes.
+ * @param fileName The name of the file being read.
+ * @param commentPrefixes the collection of comment prefixes.
+ */
+ protected AbstractFileProcessorBuilder(final String fileName, final Iterable commentPrefixes, final boolean includeProcessorFile) {
+ this(fileName, commentPrefixes == null ? StringUtils::isNotBlank : ExclusionUtils.commentFilter(commentPrefixes), includeProcessorFile);
+ }
+
+ /**
+ * Constructor for single comment prefix
+ * @param fileName The name of the file to process.
+ * @param commentPrefix the comment prefix
+ */
+ protected AbstractFileProcessorBuilder(final String fileName, final String commentPrefix, final boolean includeProcessorFile) {
+ this(fileName, commentPrefix == null ? null : Collections.singletonList(commentPrefix), includeProcessorFile);
+ }
+
+ /**
+ * Constructor for single comment prefix
+ * @param fileName The name of the file to process.
+ * @param commentFilter the comment prefix filter.
+ */
+ protected AbstractFileProcessorBuilder(final String fileName, final Predicate commentFilter, final boolean includeProcessorFile) {
+ this.levelBuilders = new TreeMap<>();
+ this.fileName = fileName;
+ this.commentFilter = commentFilter;
+ this.includeProcessorFile = includeProcessorFile;
+ }
+
+ /**
+ * Creates the MatcherSet from each level and returns them in a list in reverse order.
+ * @return a list of MatcherSet
+ */
+
+ private List createMatcherSetList() {
+ List keys = new ArrayList<>(levelBuilders.keySet());
+ keys.sort((a, b) -> -1 * Integer.compare(a, b));
+ return keys.stream().map(key -> levelBuilders.get(key).asMatcherSet()).collect(Collectors.toList());
+ }
+
+ /**
+ * Builder the list of MatcherSet that define the inclusions/exclusions for the file processor.
+ * @param root the directory against which name resolution should be made.
+ * @return the List of MatcherSet that represent this file processor.
+ */
+ public final List build(final DocumentName root) {
+ if (includeProcessorFile) {
+ String name = String.format("**/%s", fileName);
+ String pattern = ExclusionUtils.qualifyPattern(root, name);
+ MatcherSet matcherSet = new MatcherSet.Builder()
+ .addExcluded(new DocumentNameMatcher(name, MatchPatterns.from(root.getDirectorySeparator(), Collections.singletonList(pattern)), root))
+ .build();
+ LevelBuilder levelBuilder = levelBuilders.computeIfAbsent(0, k -> new LevelBuilder());
+ levelBuilder.add(matcherSet);
+ }
+
+ checkDirectory(0, root, root, new NameFileFilter(fileName));
+
+ List result = levelBuilders.size() == 1 ? Collections.singletonList(levelBuilders.get(0).asMatcherSet())
+ : createMatcherSetList();
+ levelBuilders.clear();
+ return result;
+ }
+
+ /**
+ * Process by reading the file, creating a MatcherSet, and adding it to the
+ * matcherSets.
+ * @param matcherSetConsumer the consumer to add the custom matcher sets to.
+ * @param root The root against which to resolve names.
+ * @param documentName the file to read.
+ * @return A matcher set based on the strings in the file.
+ */
+ protected MatcherSet process(final Consumer matcherSetConsumer, final DocumentName root, final DocumentName documentName) {
+ final MatcherSet.Builder matcherSetBuilder = new MatcherSet.Builder();
+ final List iterable = new ArrayList<>();
+ ExclusionUtils.asIterator(documentName.asFile(), commentFilter)
+ .map(entry -> modifyEntry(matcherSetConsumer, documentName, entry).orElse(null))
+ .filter(Objects::nonNull)
+ .map(entry -> ExclusionUtils.qualifyPattern(documentName, entry))
+ .forEachRemaining(iterable::add);
+
+ Set included = new HashSet<>();
+ Set excluded = new HashSet<>();
+ MatcherSet.Builder.segregateList(excluded, included, iterable);
+ DocumentName displayName = DocumentName.builder(root).setName(documentName.getName()).build();
+ matcherSetBuilder.addExcluded(displayName, excluded);
+ matcherSetBuilder.addIncluded(displayName, included);
+ return matcherSetBuilder.build();
+ }
+
+ /**
+ * Process the directory tree looking for files that match the filter. Call {@link #process} on any matching file.
+ * @param level the level being precessed
+ * @param root the directory against which names should be resolved.
+ * @param directory The name of the directory to process.
+ * @param fileFilter the filter to detect processable files with.
+ */
+ private void checkDirectory(final int level, final DocumentName root, final DocumentName directory, final FileFilter fileFilter) {
+ File dirFile = directory.asFile();
+ for (File file : listFiles(dirFile, fileFilter)) {
+ LevelBuilder levelBuilder = levelBuilders.computeIfAbsent(level, k -> new LevelBuilder());
+ levelBuilder.add(process(levelBuilder::add, root, DocumentName.builder(file).build()));
+ }
+ for (File dir : listFiles(dirFile, DirectoryFileFilter.DIRECTORY)) {
+ checkDirectory(level + 1, root, DocumentName.builder(dir).setBaseName(directory.getBaseName()).build(), fileFilter);
+ }
+ }
+
+ /**
+ * Allows modification of the file entry to match the {@link MatchPattern} format.
+ * Default implementation returns the @{code entry} argument.
+ * @param documentName the name of the document that the file was read from.
+ * @param entry the entry from that document.
+ * @return the modified string or an empty Optional to skip the string.
+ */
+ protected Optional modifyEntry(final Consumer matcherSetConsumer, final DocumentName documentName, final String entry) {
+ return Optional.of(entry);
+ }
+
+ /**
+ * Create a list of files by applying the filter to the specified directory.
+ * @param dir the directory.
+ * @param filter the filter.
+ * @return an array of files. May be empty but will not be null.
+ */
+ protected File[] listFiles(final File dir, final FileFilter filter) {
+ File[] result = dir.listFiles(filter);
+ return result == null ? new File[0] : result;
+ }
+
+ /**
+ * Manages the merging of {@link MatcherSet}s for the specified level.
+ */
+ private static class LevelBuilder {
+ /**
+ * The list of MatcherSets that this builder produced.
+ */
+ private final MatcherSet.Builder builder = new MatcherSet.Builder();
+
+ /**
+ * Adds a MatcherSet to this level.
+ * @param matcherSet the matcher set to add.
+ */
+ public void add(final MatcherSet matcherSet) {
+ matcherSet.includes().ifPresent(builder::addIncluded);
+ matcherSet.excludes().ifPresent(builder::addExcluded);
+ }
+
+ /**
+ * Constructs the MatcherSet for this level.
+ * @return the MatcherSet.
+ */
+ public MatcherSet asMatcherSet() {
+ return builder.build();
+ }
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilder.java
similarity index 71%
rename from apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreProcessor.java
rename to apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilder.java
index 65217c37f..2be97f983 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreProcessor.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilder.java
@@ -18,6 +18,10 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+import org.apache.rat.config.exclusion.MatcherSet;
import org.apache.rat.document.DocumentName;
import static java.lang.String.format;
@@ -25,21 +29,21 @@
/**
* A processor for {@code .bzrignore} files.
*/
-public final class BazaarIgnoreProcessor extends DescendingFileProcessor {
+public final class BazaarIgnoreBuilder extends AbstractFileProcessorBuilder {
/**
* Constructor.
*/
- public BazaarIgnoreProcessor() {
- super(".bzrignore", "#");
+ public BazaarIgnoreBuilder() {
+ super(".bzrignore", "#", true);
}
@Override
- public String modifyEntry(final DocumentName baseName, final String entry) {
+ public Optional modifyEntry(final Consumer matcherSetConsumer, final DocumentName baseName, final String entry) {
if (entry.startsWith("RE:")) {
String line = entry.substring("RE:".length()).trim();
String pattern = line.startsWith("^") ? line.substring(1) : line;
- return format(REGEX_FMT, pattern);
+ return Optional.of(format(REGEX_FMT, pattern));
}
- return entry;
+ return Optional.of(entry);
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilder.java
similarity index 63%
rename from apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessor.java
rename to apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilder.java
index a1f6582c2..8f0fc5efb 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessor.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilder.java
@@ -19,39 +19,45 @@
package org.apache.rat.config.exclusion.fileProcessors;
import java.io.File;
-import java.util.ArrayList;
+import java.util.HashSet;
import java.util.Iterator;
-import java.util.List;
+import java.util.Set;
+import java.util.function.Consumer;
import org.apache.commons.lang3.StringUtils;
import org.apache.rat.config.exclusion.ExclusionUtils;
+import org.apache.rat.config.exclusion.MatcherSet;
import org.apache.rat.document.DocumentName;
/**
* A file processor for the {@code .csvignore} file.
+ * @see Ignoring files via cvsignore
+ *
+ * The patterns found in {@code .csvignore} are only valid for the directory that contains them, not for any subdirectories.
+ *
*/
-public class CVSFileProcessor extends DescendingFileProcessor {
+public class CVSIgnoreBuilder extends AbstractFileProcessorBuilder {
/**
* The constructor.
*/
- public CVSFileProcessor() {
- super(".cvsignore", (String) null);
+ public CVSIgnoreBuilder() {
+ super(".cvsignore", (String) null, true);
}
@Override
- protected List process(final DocumentName documentName) {
+ protected MatcherSet process(final Consumer matcherSetConsumer, final DocumentName root, final DocumentName documentName) {
final File dir = new File(documentName.getName());
- List result = new ArrayList<>();
+ Set result = new HashSet<>();
Iterator iter = ExclusionUtils.asIterator(dir, StringUtils::isNotBlank);
while (iter.hasNext()) {
String line = iter.next();
String[] parts = line.split("\\s+");
for (String part : parts) {
if (!part.isEmpty()) {
- result.add(this.localizePattern(documentName, part));
+ result.add(ExclusionUtils.qualifyPattern(documentName, part));
}
}
}
- return result;
+ return new MatcherSet.Builder().addExcluded(documentName, result).build();
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessor.java
deleted file mode 100644
index 438f00752..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessor.java
+++ /dev/null
@@ -1,121 +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.config.exclusion.fileProcessors;
-
-import java.io.File;
-import java.io.FileFilter;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Objects;
-import java.util.function.Predicate;
-
-import org.apache.commons.io.filefilter.DirectoryFileFilter;
-import org.apache.commons.io.filefilter.NameFileFilter;
-import org.apache.commons.lang3.StringUtils;
-import org.apache.rat.config.exclusion.ExclusionUtils;
-import org.apache.rat.config.exclusion.FileProcessor;
-import org.apache.rat.document.DocumentName;
-
-/**
- * A FileProcessor that assumes the files contain the already formatted strings and just need to be
- * localized for the fileName.
- */
-public class DescendingFileProcessor extends FileProcessor {
- /** The name of the file being processed */
- private final String fileName;
- /** The predicate that will return {@code false} for any comment line in the file. */
- protected final Predicate commentFilter;
-
- /**
- * Constructor.
- * @param fileName The name of the file to process.
- * @param commentPrefix the comment prefix
- */
- public DescendingFileProcessor(final String fileName, final String commentPrefix) {
- this(fileName, commentPrefix == null ? null : Collections.singletonList(commentPrefix));
- }
-
- /**
- * Constructor.
- * @param fileName name of the file to process
- * @param commentPrefixes a collection of comment prefixes.
- */
- public DescendingFileProcessor(final String fileName, final Iterable commentPrefixes) {
- super();
- this.fileName = fileName;
- // null prefixes = check prefix may not be blank.
- this.commentFilter = commentPrefixes == null ? StringUtils::isNotBlank : ExclusionUtils.commentFilter(commentPrefixes);
- }
-
- /**
- * Process by reading the file and return a list of properly formatted patterns.
- * The default implementation does the following:
- *
- *
reads lines from the file specified by documentName
- *
modifies those entries by calling {@link FileProcessor#modifyEntry(DocumentName, String)}
- *
further modifies the entry by calling {@link FileProcessor#localizePattern(DocumentName, String)}
- *
retrieving the name from the resulting DocumentName
- *
- * @param documentName the file to read.
- * @return the list of properly formatted patterns
- */
- protected List process(final DocumentName documentName) {
- return ExclusionUtils.asIterator(new File(documentName.getName()), commentFilter)
- .map(entry -> this.modifyEntry(documentName, entry))
- .filter(Objects::nonNull)
- .map(entry -> this.localizePattern(documentName, entry))
- .addTo(new ArrayList<>());
- }
-
- /**
- * Create a list of files by applying the filter to the specified directory.
- * @param dir the directory.
- * @param filter the filter.
- * @return an array of files. May be empty but will not be null.
- */
- private File[] listFiles(final File dir, final FileFilter filter) {
- File[] result = dir.listFiles(filter);
- return result == null ? new File[0] : result;
- }
-
- /**
- * Process the directory tree looking for files that match the filter. Process any matching file and return
- * a list of fully qualified patterns.
- * @param directory The name of the directory to process.
- * @param fileFilter the filter to detect processable files with.
- * @return the list of fully qualified file patterns.
- */
- protected List checkDirectory(final DocumentName directory, final FileFilter fileFilter) {
- List fileNames = new ArrayList<>();
- File dirFile = new File(directory.getName());
- for (File f : listFiles(dirFile, fileFilter)) {
- fileNames.addAll(process(DocumentName.builder(f).setBaseName(directory.getBaseName()).build()));
- }
- for (File dir : listFiles(dirFile, DirectoryFileFilter.DIRECTORY)) {
- fileNames.addAll(checkDirectory(DocumentName.builder(dir).build(), fileFilter));
- }
- return fileNames;
- }
-
- @Override
- public List apply(final DocumentName dir) {
- return checkDirectory(dir, new NameFileFilter(fileName));
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessor.java
deleted file mode 100644
index 8cf2d0960..000000000
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessor.java
+++ /dev/null
@@ -1,70 +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.config.exclusion.fileProcessors;
-
-import java.io.File;
-
-import org.apache.rat.config.exclusion.plexus.MatchPatterns;
-import org.apache.rat.document.DocumentName;
-import org.apache.rat.document.DocumentNameMatcher;
-
-/**
- * Processes the .gitignore file.
- * @see .gitignore documentation
- */
-public class GitFileProcessor extends DescendingFileProcessor {
-
- /**
- * Constructs a file processor that processes a .gitignore file and ignores any lines starting with "#".
- */
- public GitFileProcessor() {
- super(".gitignore", "#");
- }
-
- @Override
- public String modifyEntry(final DocumentName documentName, final String entry) {
- // An optional prefix "!" which negates the pattern;
- boolean prefix = entry.startsWith("!");
- String pattern = prefix || entry.startsWith("\\#") || entry.startsWith("\\!") ? entry.substring(1) : entry;
-
- // If there is a separator at the beginning or middle (or both) of the pattern, then
- // the pattern is relative to the directory level of the particular .gitignore file itself.
- // Otherwise, the pattern may also match at any level below the .gitignore level.
- int slashPos = pattern.indexOf("/");
- // no slash or at end already
- if (slashPos == -1 || slashPos == pattern.length() - 1) {
- pattern = "**/" + pattern;
- }
- if (slashPos == 0) {
- pattern = pattern.substring(1);
- }
- // If there is a separator at the end of the pattern then the pattern will only match directories,
- // otherwise the pattern can match both files and directories.
- if (pattern.endsWith("/")) {
- pattern = pattern.substring(0, pattern.length() - 1);
- String name = prefix ? "!" + pattern : pattern;
- DocumentName matcherPattern = DocumentName.builder(documentName).setName(name.replace("/", documentName.getDirectorySeparator()))
- .build();
- customMatchers.add(DocumentNameMatcher.and(new DocumentNameMatcher("isDirectory", File::isDirectory),
- new DocumentNameMatcher(name, MatchPatterns.from(matcherPattern.localized("/")))));
- return null;
- }
- return prefix ? "!" + pattern : pattern;
- }
-}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilder.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilder.java
new file mode 100644
index 000000000..cf4e9fb92
--- /dev/null
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilder.java
@@ -0,0 +1,105 @@
+/*
+ * 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.exclusion.fileProcessors;
+
+import java.io.File;
+import java.util.Optional;
+import java.util.function.Consumer;
+
+import org.apache.rat.config.exclusion.ExclusionUtils;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.config.exclusion.plexus.MatchPatterns;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+
+import static org.apache.rat.config.exclusion.ExclusionUtils.NEGATION_PREFIX;
+
+/**
+ * Processes the {@code .gitignore} file.
+ * @see .gitignore documentation
+ */
+public class GitIgnoreBuilder extends AbstractFileProcessorBuilder {
+ /** The name of the file we read from */
+ private static final String IGNORE_FILE = ".gitignore";
+ /** The comment prefix */
+ private static final String COMMENT_PREFIX = "#";
+ /** An escaped comment in the .gitignore file. (Not a comment) */
+ private static final String ESCAPED_COMMENT = "\\#";
+ /** An escaped negation in the .gitignore file. (Not a negation) */
+ private static final String ESCAPED_NEGATION = "\\!";
+ /** The slash string */
+ private static final String SLASH = "/";
+
+ /**
+ * Constructs a file processor that processes a {@code .gitignore} file and ignores any lines starting with {@value #COMMENT_PREFIX}.
+ */
+ public GitIgnoreBuilder() {
+ super(IGNORE_FILE, COMMENT_PREFIX, true);
+ }
+
+ /**
+ * Convert the string entry.
+ * If the string ends with a slash an {@link DocumentNameMatcher#and} is constructed from a directory check and the file
+ * name matcher. In this case an empty Optional is returned.
+ * If the string starts with {@value ExclusionUtils#NEGATION_PREFIX} then the entry is placed in the include list, otherwise
+ * the entry is placed in the exclude list and the name of the check returned.
+ * @param documentName The name of the document being processed.
+ * @param entry The entry from the document
+ * @return and Optional containing the name of the matcher.
+ */
+ @Override
+ protected Optional modifyEntry(final Consumer matcherSetConsumer, final DocumentName documentName, final String entry) {
+ // An optional prefix "!" which negates the pattern;
+ boolean prefix = entry.startsWith(NEGATION_PREFIX);
+ String pattern = prefix || entry.startsWith(ESCAPED_COMMENT) || entry.startsWith(ESCAPED_NEGATION) ?
+ entry.substring(1) : entry;
+
+ // If there is a separator at the beginning or middle (or both) of the pattern, then
+ // the pattern is relative to the directory level of the particular .gitignore file itself.
+ // Otherwise, the pattern may also match at any level below the .gitignore level.
+ int slashPos = pattern.indexOf(SLASH);
+ // no slash or at end already
+ if (slashPos == -1 || slashPos == pattern.length() - 1) {
+ pattern = "**/" + pattern;
+ }
+ if (slashPos == 0) {
+ pattern = pattern.substring(1);
+ }
+ // If there is a separator at the end of the pattern then the pattern will only match directories,
+ // otherwise the pattern can match both files and directories.
+ if (pattern.endsWith(SLASH)) {
+ pattern = pattern.substring(0, pattern.length() - 1);
+ String name = prefix ? NEGATION_PREFIX + pattern : pattern;
+ DocumentName matcherPattern = DocumentName.builder(documentName).setName(name.replace(SLASH, documentName.getDirectorySeparator()))
+ .build();
+ DocumentNameMatcher matcher = DocumentNameMatcher.and(new DocumentNameMatcher("isDirectory", File::isDirectory),
+ new DocumentNameMatcher(name, MatchPatterns.from(matcherPattern.localized(documentName.getDirectorySeparator()))));
+
+ MatcherSet.Builder builder = new MatcherSet.Builder();
+ if (prefix) {
+ builder.addIncluded(matcher);
+ } else {
+ builder.addExcluded(matcher);
+ }
+ matcherSetConsumer.accept(builder.build());
+ return Optional.empty();
+ }
+ return Optional.of(prefix ? NEGATION_PREFIX + pattern : pattern);
+ }
+}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilder.java
similarity index 59%
rename from apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessor.java
rename to apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilder.java
index d88e60c50..1698d85b9 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessor.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilder.java
@@ -18,19 +18,23 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
-import java.util.List;
import java.util.Locale;
+import java.util.Optional;
+import java.util.function.Consumer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
+import org.apache.rat.config.exclusion.MatcherSet;
import org.apache.rat.document.DocumentName;
import static java.lang.String.format;
/**
* A processor for the {@code .hgignore} files.
+ * @see Mecurial how to ignore files
+ * @see syntax for Mercurial ignore files
*/
-public final class HgIgnoreProcessor extends DescendingFileProcessor {
+public final class HgIgnoreBuilder extends AbstractFileProcessorBuilder {
/**
* The state enumeration for the processor. When processing the file the processor changes
* syntax state depending on the input.
@@ -48,30 +52,38 @@ enum Syntax {
private Syntax state;
/**
- * Constructs the .hgignore processor.
+ * Constructs the {@code .hgignore} processor.
*/
- public HgIgnoreProcessor() {
- super(".hgignore", "#");
+ public HgIgnoreBuilder() {
+ super(".hgignore", "#", true);
state = Syntax.REGEXP;
}
@Override
- protected List process(final DocumentName baseName) {
+ protected MatcherSet process(final Consumer matcherSetConsumer, final DocumentName root, final DocumentName documentName) {
state = Syntax.REGEXP;
- return super.process(baseName);
+ return super.process(matcherSetConsumer, root, documentName);
}
@Override
- public String modifyEntry(final DocumentName baseName, final String entry) {
+ public Optional modifyEntry(final Consumer matcherSetConsumer, final DocumentName documentName, final String entry) {
Matcher m = SYNTAX_CHECK.matcher(entry.toLowerCase(Locale.ROOT));
if (m.matches()) {
state = Syntax.valueOf(m.group(1).toUpperCase());
- return null;
+ return Optional.empty();
}
+ /*
+ Neither glob nor regexp patterns are rooted. A glob-syntax pattern of the form *.c will match a file ending in .c
+ in any directory, and a regexp pattern of the form \.c$ will do the same. To root a regexp pattern, start it with ^.
+ */
if (state == Syntax.REGEXP) {
String pattern = entry.startsWith("^") ? entry.substring(1) : ".*" + entry;
- return format(REGEX_FMT, pattern);
+ return Optional.of(format(REGEX_FMT, pattern));
+ } else {
+ if (entry.startsWith("*")) {
+ return Optional.of("**/" + entry);
+ }
}
- return entry;
+ return Optional.of(entry);
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/help/Help.java b/apache-rat-core/src/main/java/org/apache/rat/help/Help.java
index 06202375e..8623c175d 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/help/Help.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/help/Help.java
@@ -85,7 +85,7 @@ public void printUsage(final Options opts) {
helpFormatter.printWrapped(writer, helpFormatter.getWidth(), helpFormatter.getLeftPadding() + HELP_PADDING + HELP_PADDING,
argumentPadding + "Provides a path matcher: " + sc.hasStaticDocumentNameMatcher());
helpFormatter.printWrapped(writer, helpFormatter.getWidth(), helpFormatter.getLeftPadding() + HELP_PADDING + HELP_PADDING,
- argumentPadding + "Provides a file processor: " + sc.fileProcessor().hasNext());
+ argumentPadding + "Provides a file processor: " + sc.fileProcessorBuilder().hasNext());
}
writer.println("\nA path matcher will match specific information about the file.");
writer.println("\nA file processor will process the associated \"ignore\" file for include and exclude directives");
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java
index 5a9186f83..9f62c6fc3 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/StandardCollectionTest.java
@@ -36,7 +36,7 @@ public class StandardCollectionTest {
@ParameterizedTest
@MethodSource("collectionData")
public void testState(StandardCollection scm, boolean hasFileProcessor, boolean hasPathMatchSupplier, boolean hasPatterns) {
- assertEquals(hasFileProcessor, scm.fileProcessor().hasNext(), () -> scm.name() + " FileProcessor state wrong.");
+ assertEquals(hasFileProcessor, scm.fileProcessorBuilder().hasNext(), () -> scm.name() + " MatcherSet state wrong.");
assertEquals(hasPathMatchSupplier, scm.hasStaticDocumentNameMatcher(), () -> scm.name() + " PathMatcherSupplier state wrong.");
assertEquals(hasPatterns, !scm.patterns().isEmpty(), () -> scm.name() + " patterns state wrong.");
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreBuilderTest.java
new file mode 100644
index 000000000..09c330f82
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreBuilderTest.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.config.exclusion.fileProcessors;
+
+import java.nio.file.Path;
+import java.util.List;
+import java.util.stream.Stream;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.config.exclusion.plexus.SelectorUtils;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+import org.apache.rat.document.DocumentNameMatcherTest;
+import org.apache.rat.document.FSInfoTest;
+import org.junit.jupiter.api.AfterEach;
+import org.junit.jupiter.api.BeforeEach;
+import org.junit.jupiter.api.condition.EnabledOnOs;
+import org.junit.jupiter.api.condition.OS;
+import org.junit.jupiter.api.io.TempDir;
+
+import java.io.File;
+import java.io.FileWriter;
+import java.io.IOException;
+import java.io.PrintWriter;
+import org.junit.jupiter.params.provider.Arguments;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+/**
+ * The base class for FileProcessor builder tests.
+ * Provides supporting methods for creating test files and for validating results.
+ */
+public class AbstractIgnoreBuilderTest {
+
+ @TempDir
+ protected Path tmpPath;
+ protected DocumentName baseName;
+
+ @BeforeEach
+ protected void setup() throws IOException {
+ baseName = DocumentName.builder(tmpPath.toFile()).build();
+ }
+
+ @AfterEach
+ @EnabledOnOs(OS.WINDOWS)
+ void reset() {
+ baseName = null;
+ }
+
+ /**
+ * This method is a known workaround for
+ * {@link junit 5 issue #2811 }.
+ */
+ @AfterEach
+ @EnabledOnOs(OS.WINDOWS)
+ void cleanUp() {
+ System.gc();
+ }
+
+ /**
+ * Writes a text file to the baseDir directory.
+ * @param name the name of the file.
+ * @param lines the lines to write to the file.
+ * @return the File that was written.
+ * @throws IOException if file cannot be created.
+ */
+ protected File writeFile(String name, Iterable lines) throws IOException {
+ File file = new File(tmpPath.toFile(), name);
+ try (PrintWriter writer = new PrintWriter(new FileWriter(file))) {
+ lines.forEach(writer::println);
+ }
+ return file;
+ }
+
+ /**
+ * Asserts the correctness of the excluder. An excluder returns false if the document name is matched.
+ * @param builder An FileProcessorBuilder that will create the excluder.
+ * @param matching the matching strings.
+ * @param notMatching the non-matching strings.
+ */
+ protected void assertCorrect(AbstractFileProcessorBuilder builder, Iterable matching, Iterable notMatching) {
+ assertCorrect(builder.build(baseName), baseName, matching, notMatching);
+ }
+
+ /**
+ * Asserts the correctness of the excluder. An excluder returns false if the document name is matched.
+ * @param matcherSets the list of matchers to create the DocumentNameMatcher from.
+ * @param baseDir the base directory for the excluder test.
+ * @param matching the matching strings.
+ * @param notMatching the non-matching strings.
+ */
+ protected void assertCorrect(List matcherSets, DocumentName baseDir, Iterable matching, Iterable notMatching) {
+ DocumentNameMatcher excluder = MatcherSet.merge(matcherSets).createMatcher();
+ for (String name : matching) {
+ DocumentName docName = baseDir.resolve(SelectorUtils.extractPattern(name, baseDir.getDirectorySeparator()));
+ assertThat(excluder.matches(docName)).as(() -> DocumentNameMatcherTest.processDecompose(excluder, docName)).isFalse();
+ }
+ for (String name : notMatching) {
+ DocumentName docName = baseDir.resolve(SelectorUtils.extractPattern(name, baseDir.getDirectorySeparator()));
+ assertThat(excluder.matches(docName)).as(() -> DocumentNameMatcherTest.processDecompose(excluder, docName)).isTrue();
+ }
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreProcessorTest.java
deleted file mode 100644
index 741a1ab44..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/AbstractIgnoreProcessorTest.java
+++ /dev/null
@@ -1,62 +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.config.exclusion.fileProcessors;
-
-import org.apache.rat.document.DocumentName;
-import org.junit.jupiter.api.AfterEach;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.condition.EnabledOnOs;
-import org.junit.jupiter.api.condition.OS;
-import org.junit.jupiter.api.io.TempDir;
-
-import java.io.File;
-import java.io.FileWriter;
-import java.io.IOException;
-import java.io.PrintWriter;
-
-public class AbstractIgnoreProcessorTest {
-
- @TempDir
- protected File baseDir;
- protected DocumentName baseName;
-
- @BeforeEach
- public void setup() {
- baseName = DocumentName.builder(baseDir).build();
- }
-
- /**
- * This method is a known workaround for
- * {@link junit 5 issue #2811 }.
- */
- @AfterEach
- @EnabledOnOs(OS.WINDOWS)
- void cleanUp() {
- System.gc();
- }
-
- protected File writeFile(String name, Iterable lines) throws IOException {
- File file = new File(baseDir, name);
- try (PrintWriter writer = new PrintWriter(new FileWriter(file))) {
- lines.forEach(writer::println);
- }
- return file;
- }
-
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilderTest.java
new file mode 100644
index 000000000..dc3c352c1
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/BazaarIgnoreBuilderTest.java
@@ -0,0 +1,43 @@
+/*
+ * 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.exclusion.fileProcessors;
+
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.util.Arrays;
+import java.util.List;
+
+public class BazaarIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
+
+ @Test
+ public void processExampleFileTest() throws IOException {
+ String[] lines = {
+ "# a comment", "*.elc", "*.pyc", "*~", System.lineSeparator(),
+ "# switch to regexp syntax.", "RE:^\\.pc" };
+
+ List matching = Arrays.asList("test.elc", "test.pyc", "test.thing~", ".pc");
+ List notMatching = Arrays.asList("test.foo", ".pc/stuff", "subidr/test.elc");
+
+ writeFile(".bzrignore", Arrays.asList(lines));
+
+ assertCorrect(new BazaarIgnoreBuilder(), matching, notMatching);
+ }
+
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilderTest.java
similarity index 65%
rename from apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
rename to apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilderTest.java
index 7900fd7e7..7a0d37dcb 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSFileProcessorTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/CVSIgnoreBuilderTest.java
@@ -18,32 +18,29 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
-import java.util.ArrayList;
-
-import org.apache.rat.utils.ExtendedIterator;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.document.DocumentNameMatcher;
import org.junit.jupiter.api.Test;
-import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class CVSFileProcessorTest extends AbstractIgnoreProcessorTest {
+public class CVSIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
@Test
public void processExampleFileTest() throws IOException {
String[] lines = {
"thingone thingtwo", System.lineSeparator(), "one_fish", "two_fish", "", "red_* blue_*"};
- List expected = ExtendedIterator.create(Arrays.asList("thingone", "thingtwo", "one_fish", "two_fish", "red_*", "blue_*").iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new ArrayList<>());
+ List matching = Arrays.asList("thingone", "thingtwo", "one_fish", "two_fish", "red_fish", "blue_fish");
+ List notMatching = Arrays.asList("thing", "two", "fish_red", "subdir/two_fish", "subdir/red_fish", "subdir/blue_fish");
writeFile(".cvsignore", Arrays.asList(lines));
- CVSFileProcessor processor = new CVSFileProcessor();
- List actual = processor.apply(baseName);
- assertEquals(expected, actual);
+ CVSIgnoreBuilder processor = new CVSIgnoreBuilder();
+ DocumentNameMatcher matcher = MatcherSet.merge(processor.build(baseName)).createMatcher();
+
+ assertCorrect(new CVSIgnoreBuilder(), matching, notMatching);
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessorTest.java
deleted file mode 100644
index e3343c1d5..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/DescendingFileProcessorTest.java
+++ /dev/null
@@ -1,70 +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.config.exclusion.fileProcessors;
-
-import java.util.ArrayList;
-import org.apache.rat.document.DocumentName;
-import org.apache.rat.utils.ExtendedIterator;
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.Arrays;
-import java.util.Collections;
-import java.util.List;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class DescendingFileProcessorTest extends AbstractIgnoreProcessorTest {
-
- @Test
- public void singleDirectoryTest() throws IOException {
- String[] lines = {"*.ext", "fname.*", "**/fname.ext"};
-
- List expected = ExtendedIterator.create(Arrays.asList(lines).iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new ArrayList<>());
-
- writeFile("test.txt", Arrays.asList(lines));
- DocumentName documentName = DocumentName.builder(baseDir).build();
-
- DescendingFileProcessor processor = new DescendingFileProcessor("test.txt", "#");
- List actual = processor.apply(baseName);
- assertThat(actual).isEqualTo(expected);
- }
-
- @Test
- public void layeredDirectoryTest() throws IOException {
- String[] lines = {"*.ext", "fname.*", "**/fname.ext"};
-
- List expected = ExtendedIterator.create(Arrays.asList(lines).iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new ArrayList<>());
-
- writeFile("test.txt", Arrays.asList(lines));
-
- File subdir = new File(baseDir, "subdir");
- assertThat(subdir.mkdirs()).as("Could not make subdirectory").isTrue();
-
- writeFile("subdir/test.txt", Collections.singletonList("foo.*"));
- expected.add(new File(subdir, "foo.*").getPath());
-
- DescendingFileProcessor processor = new DescendingFileProcessor("test.txt", "#");
- List actual = processor.apply(baseName);
- assertThat(actual).isEqualTo(expected);
- }
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessorTest.java
deleted file mode 100644
index 3166b4ca7..000000000
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitFileProcessorTest.java
+++ /dev/null
@@ -1,118 +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.config.exclusion.fileProcessors;
-
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.stream.Stream;
-import org.apache.rat.document.DocumentName;
-import org.apache.rat.document.DocumentNameMatcher;
-import org.apache.rat.utils.ExtendedIterator;
-import org.junit.Ignore;
-import org.junit.jupiter.api.Test;
-
-import java.io.File;
-import java.io.IOException;
-import java.net.URL;
-import java.util.Arrays;
-import java.util.List;
-import org.junit.jupiter.params.ParameterizedTest;
-import org.junit.jupiter.params.provider.Arguments;
-import org.junit.jupiter.params.provider.MethodSource;
-
-import static org.assertj.core.api.Assertions.assertThat;
-
-public class GitFileProcessorTest extends AbstractIgnoreProcessorTest {
-
- @Test
- public void processExampleFileTest() throws IOException {
- String[] lines = {
- "# somethings",
- "!thingone", "thing*", System.lineSeparator(),
- "# some fish",
- "**/fish", "*_fish",
- "# some colorful directories",
- "red/", "blue/*/"};
-
- List expected = ExtendedIterator.create(Arrays.asList("**/thing*", "**/fish", "**/*_fish").iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new ArrayList<>());
- expected.add(0, "!"+new File(baseDir, "**/thingone").getPath());
- // "thingone",
- writeFile(".gitignore", Arrays.asList(lines));
-
- GitFileProcessor processor = new GitFileProcessor();
- List actual = processor.apply(baseName);
- assertThat(actual).isEqualTo(expected);
-
- actual.clear();
- processor.customDocumentNameMatchers().forEach(x -> actual.add(x.toString()));
- expected.clear();
- ExtendedIterator.create(Arrays.asList("**/red", "blue/*").iterator())
- .map(s -> String.format("and(isDirectory, %s)", s))
- .forEachRemaining(expected::add);
- assertThat(actual).isEqualTo(expected);
- }
-
- // see https://git-scm.com/docs/gitignore
- @ParameterizedTest
- @MethodSource("modifyEntryData")
- public void modifyEntryTest(String source, String expected) {
- GitFileProcessor underTest = new GitFileProcessor();
- DocumentName testName = DocumentName.builder().setName("GitFileProcessorTest").setBaseName("testDir").build();
- if (source.endsWith("/")) {
- assertThat(underTest.modifyEntry(testName, source)).isEqualTo(null);
- Iterator iter = underTest.customDocumentNameMatchers().iterator();
- assertThat(iter).hasNext();
- assertThat(iter.next().toString()).isEqualTo(String.format("and(isDirectory, %s)", expected));
- } else {
- assertThat(underTest.modifyEntry(testName, source)).isEqualTo(expected);
- assertThat(underTest.customDocumentNameMatchers().iterator().hasNext()).isFalse();
- }
- }
-
- private static Stream modifyEntryData() {
- List lst = new ArrayList<>();
-
- lst.add(Arguments.of("\\#filename", "**/#filename"));
-
- lst.add(Arguments.of("!#filename", "!**/#filename"));
- lst.add(Arguments.of("\\#filename", "**/#filename"));
- lst.add(Arguments.of("!#filename", "!**/#filename"));
- lst.add(Arguments.of("/filename", "filename"));
- lst.add(Arguments.of("file/name", "file/name"));
- lst.add(Arguments.of("/file/name", "file/name"));
- lst.add(Arguments.of("filename", "**/filename"));
- lst.add(Arguments.of("filename/", "**/filename"));
- lst.add(Arguments.of("/filename/", "filename"));
-
- return lst.stream();
- }
-
- @Test
- @Ignore("RAT-335 ")
- public void test_RAT_335() {
- GitFileProcessor underTest = new GitFileProcessor();
- URL url = GitFileProcessorTest.class.getClassLoader().getResource("RAT_355/src/");
- File file = new File(url.getFile());
-
- DocumentName documentName = DocumentName.builder(file).setBaseName(File.separator).build();
- List lst = underTest.apply(documentName);
- System.out.println(lst);
- }
-}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilderTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilderTest.java
new file mode 100644
index 000000000..60f734420
--- /dev/null
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/GitIgnoreBuilderTest.java
@@ -0,0 +1,138 @@
+/*
+ * 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.exclusion.fileProcessors;
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.Optional;
+import java.util.stream.Stream;
+import org.apache.rat.config.exclusion.MatcherSet;
+import org.apache.rat.document.DocumentName;
+import org.apache.rat.document.DocumentNameMatcher;
+import org.apache.rat.document.FSInfoTest;
+import org.junit.jupiter.api.Test;
+
+import java.io.IOException;
+import java.net.URL;
+import java.util.Arrays;
+import java.util.List;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class GitIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
+
+ @Test
+ public void processExampleFileTest() throws IOException {
+ try {
+ String[] lines = {
+ "# somethings",
+ "!thingone", "thing*", System.lineSeparator(),
+ "# some fish",
+ "**/fish", "*_fish",
+ "# some colorful directories",
+ "red/", "blue/*/"};
+ List matches = Arrays.asList("some/things", "some/fish", "another/red_fish");
+
+ List notMatches = Arrays.asList("some/thingone", "thingone");
+
+ writeFile(".gitignore", Arrays.asList(lines));
+
+ assertCorrect(new GitIgnoreBuilder(), matches, notMatches);
+ } finally {
+ System.getProperties().remove("FSInfo");
+ }
+ }
+
+ // see https://git-scm.com/docs/gitignore
+ @ParameterizedTest
+ @MethodSource("modifyEntryData")
+ public void modifyEntryTest(DocumentName.FSInfo fsInfo, String source, String expected) {
+ GitIgnoreBuilder underTest = new GitIgnoreBuilder();
+ DocumentName testName = DocumentName.builder(fsInfo).setName("GitIgnoreBuilderTest").setBaseName("testDir").build();
+ List matcherSets = new ArrayList<>();
+ Optional entry = underTest.modifyEntry(matcherSets::add, testName, source);
+
+ if (source.endsWith("/")) {
+ assertThat(entry).isNotPresent();
+ assertThat(matcherSets).hasSize(1);
+ DocumentNameMatcher matcher = matcherSets.get(0).createMatcher();
+ assertThat(matcher.toString()).isEqualTo(expected);
+ } else {
+ assertThat(entry.get()).isEqualTo(expected);
+ }
+ }
+
+ private static Stream modifyEntryData() {
+ List lst = new ArrayList<>();
+ for (DocumentName.FSInfo fsInfo : FSInfoTest.TEST_SUITE) {
+ lst.add(Arguments.of(fsInfo, "\\#filename", "**/#filename"));
+
+ lst.add(Arguments.of(fsInfo, "!#filename", "!**/#filename"));
+ lst.add(Arguments.of(fsInfo, "\\#filename", "**/#filename"));
+ lst.add(Arguments.of(fsInfo, "!#filename", "!**/#filename"));
+ lst.add(Arguments.of(fsInfo, "/filename", "filename"));
+ lst.add(Arguments.of(fsInfo, "file/name", "file/name"));
+ lst.add(Arguments.of(fsInfo, "/file/name", "file/name"));
+ lst.add(Arguments.of(fsInfo, "filename", "**/filename"));
+ lst.add(Arguments.of(fsInfo, "filename/", "not(and(isDirectory, **/filename))"));
+ lst.add(Arguments.of(fsInfo, "/filename/", "not(and(isDirectory, filename))"));
+ // inclusion by itself becomes nothing.
+ lst.add(Arguments.of(fsInfo, "!filename/", "TRUE"));
+ }
+ return lst.stream();
+ }
+
+ private void assertMatches(DocumentName documentName, DocumentNameMatcher matcher, String[] matching, String[] notMatching) {
+ for (String test : matching) {
+ DocumentName name = documentName.resolve(test);
+ assertThat(matcher.matches(name)).as(test).isTrue();
+ }
+ for (String test: notMatching) {
+ DocumentName name = documentName.resolve(test);
+ assertThat(matcher.matches(name)).as(test).isFalse();
+ }
+ }
+
+ @Test
+ public void test_RAT_335() {
+ GitIgnoreBuilder underTest = new GitIgnoreBuilder();
+ URL url = GitIgnoreBuilderTest.class.getClassLoader().getResource("GitIgnoreBuilderTest/src/");
+ File file = new File(url.getFile());
+
+ DocumentName documentName = DocumentName.builder(file).build();
+ List matcherSets = underTest.build(documentName);
+ DocumentNameMatcher matcher = MatcherSet.merge(matcherSets).createMatcher();
+
+ DocumentName candidate = DocumentName.builder()
+ .setName("/home/claude/apache/creadur-rat/apache-rat-core/target/test-classes/GitIgnoreBuilderTest/src/dir1/file1.log")
+ .setBaseName("home/claude/apache/creadur-rat/apache-rat-core/target/test-classes/GitIgnoreBuilderTest/src/").build();
+ System.out.println("Decomposition for "+candidate);
+
+ assertThat(matcher.toString()).isEqualTo("matcherSet(or('included dir1/.gitignore', 'included .gitignore'), or('excluded dir1/.gitignore', **/.gitignore, 'excluded .gitignore'))");
+
+ List notMatching = Arrays.asList("README.txt", "dir1/dir1.md", "dir2/dir2.txt", "dir3/file3.log", "dir1/file1.log");
+
+ List matching = Arrays.asList(".gitignore", "root.md", "dir1/.gitignore", "dir1/dir1.txt", "dir2/dir2.md", "dir3/dir3.log");
+
+ assertCorrect(matcherSets, documentName.getBaseDocumentName(), matching, notMatching);
+ }
+}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilderTest.java
similarity index 53%
rename from apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessorTest.java
rename to apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilderTest.java
index 3085792c5..d91a157e0 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreProcessorTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/fileProcessors/HgIgnoreBuilderTest.java
@@ -18,49 +18,37 @@
*/
package org.apache.rat.config.exclusion.fileProcessors;
-import java.util.ArrayList;
-import org.apache.rat.utils.ExtendedIterator;
import org.junit.jupiter.api.Test;
-import java.io.File;
import java.io.IOException;
import java.util.Arrays;
import java.util.List;
-import static java.lang.String.format;
-import static org.junit.jupiter.api.Assertions.assertEquals;
-
-public class HgIgnoreProcessorTest extends AbstractIgnoreProcessorTest {
+public class HgIgnoreBuilderTest extends AbstractIgnoreBuilderTest {
@Test
public void processExampleFileTest() throws IOException {
String[] lines = {
- "# use glob syntax.", "syntax: glob", "*.elc", "*.pyc", "*~", System.lineSeparator(),
- "# switch to regexp syntax.", "syntax: regexp", "^\\.pc/" };
+ "# use glob syntax.", "syntax: glob", "*.elc", "*.pyc", "*~", "*.c", System.lineSeparator(),
+ "# switch to regexp syntax.", "syntax: regexp", "^\\.pc" };
- List expected = ExtendedIterator.create(Arrays.asList("*.elc", "*.pyc", "*~").iterator())
- .map(s -> new File(baseDir, s).getPath()).addTo(new ArrayList<>());
- expected.add(format("%%regex[\\Q%s%s\\E%s]", baseDir.getPath(), File.separatorChar, "\\.pc/"));
+ List matching = Arrays.asList("test.elc", "test.pyc", "subdir/test.pyc", "test.thing~", ".pc", "foo.c", "/subdir/foo.c" );
+ List notMatching = Arrays.asList("test.foo", "test.thing~/subdir", ".pc/subdir");
writeFile(".hgignore", Arrays.asList(lines));
- HgIgnoreProcessor processor = new HgIgnoreProcessor();
- List actual = processor.apply(baseName);
- assertEquals(expected, actual);
+ assertCorrect(new HgIgnoreBuilder(), matching, notMatching);
}
@Test
public void processDefaultFileTest() throws IOException {
- String[] lines = {"^[A-Z]*\\.txt", "[0-9]*\\.txt"};
+ String[] lines = {"^[A-Z]*\\.txt", "[0-9]+\\.txt"};
- List expected = ExtendedIterator.create(Arrays.asList("[A-Z]*\\.txt", ".*[0-9]*\\.txt").iterator())
- .map(s -> format("%%regex[\\Q%s%s\\E%s]", baseDir.getPath(), File.separatorChar, s))
- .addTo(new ArrayList<>());
+ List matching = Arrays.asList("ABIGNAME.txt", "endsIn9.txt");
+ List notMatching = Arrays.asList("asmallName.txt", "endsin.doc");
writeFile(".hgignore", Arrays.asList(lines));
- HgIgnoreProcessor processor = new HgIgnoreProcessor();
- List actual = processor.apply(baseName);
- assertEquals(expected, actual);
+ assertCorrect(new HgIgnoreBuilder(), matching, notMatching);
}
}
diff --git a/apache-rat-core/src/test/resources/RAT_355/commandLine.txt b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/commandLine.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/commandLine.txt
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/commandLine.txt
diff --git a/apache-rat-core/src/test/resources/RAT_355/expected-message.txt b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/expected-message.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/expected-message.txt
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/expected-message.txt
diff --git a/apache-rat-core/src/test/resources/RAT_355/pom.xml b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/pom.xml
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/pom.xml
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/pom.xml
diff --git a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/.gitignore b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/.gitignore
new file mode 100644
index 000000000..8855fa805
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/.gitignore
@@ -0,0 +1,7 @@
+*.md
+
+# This makes it ignore dir3/dir3.log and dir3/file3.log
+*.log
+
+# This makes it "unignore" dir3/file3.log
+!file*.log
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/README.txt b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/README.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/README.txt
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/README.txt
diff --git a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/.gitignore b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/.gitignore
new file mode 100644
index 000000000..26fd5c956
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/.gitignore
@@ -0,0 +1,3 @@
+*.txt
+!dir1.md
+file1.log
\ No newline at end of file
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.md
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/dir1/dir1.md
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.md
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir2/dir2.txt b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.txt
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/dir2/dir2.txt
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/dir1.txt
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/dir3/file3.log b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/file1.log
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/dir3/file3.log
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir1/file1.log
diff --git a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.md b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.txt b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.txt
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir2/dir2.txt
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/dir3.log b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/dir3.log
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/dir3.log
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/file3.log b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/file3.log
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/dir3/file3.log
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-core/src/test/resources/RAT_355/src/invoker.properties b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/invoker.properties
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/src/invoker.properties
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/invoker.properties
diff --git a/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/root.md b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/root.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/src/root.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-core/src/test/resources/RAT_355/verify.groovy b/apache-rat-core/src/test/resources/GitIgnoreBuilderTest/verify.groovy
similarity index 100%
rename from apache-rat-core/src/test/resources/RAT_355/verify.groovy
rename to apache-rat-core/src/test/resources/GitIgnoreBuilderTest/verify.groovy
From c0bb2a585a42433d1c18f5d695671190d46aa0db Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Sun, 9 Feb 2025 00:41:37 +0100
Subject: [PATCH 35/41] RAT-98: simple non-functional changes (#440)
* simple non-functional changes
* Minor changes during review
---------
Co-authored-by: P. Ottlinger
---
.../main/java/org/apache/rat/analysis/TikaProcessor.java | 9 ++++-----
.../rat/config/exclusion/plexus/SelectorUtils.java | 1 -
.../org/apache/rat/document/ArchiveEntryDocument.java | 6 +++---
.../java/org/apache/rat/anttasks/ReportOptionTest.java | 2 +-
4 files changed, 8 insertions(+), 10 deletions(-)
diff --git a/apache-rat-core/src/main/java/org/apache/rat/analysis/TikaProcessor.java b/apache-rat-core/src/main/java/org/apache/rat/analysis/TikaProcessor.java
index 5f128668d..d437c7733 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/analysis/TikaProcessor.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/analysis/TikaProcessor.java
@@ -39,11 +39,11 @@
import org.apache.tika.parser.txt.CharsetMatch;
/**
- * A wrapping around the tika processor.
+ * A wrapping around the Tika processor.
*/
public final class TikaProcessor {
- /** the Tika parser */
+ /** The Tika parser */
private static final Tika TIKA = new Tika();
/** A map of mime type string to non-BINARY types.
* "text" types are already handled somewhere else
@@ -129,9 +129,9 @@ public static InputStream markSupportedInputStream(final InputStream stream) {
* @throws RatDocumentAnalysisException on error.
*/
public static String process(final Document document) throws RatDocumentAnalysisException {
- Metadata metadata = new Metadata();
try (InputStream stream = markSupportedInputStream(document.inputStream())) {
- metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, document.getName().getName());
+ Metadata metadata = new Metadata();
+ metadata.set(TikaCoreProperties.RESOURCE_NAME_KEY, document.getName().getShortName());
String result = TIKA.detect(stream, metadata);
String[] parts = result.split("/");
MediaType mediaType = new MediaType(parts[0], parts[1]);
@@ -146,7 +146,6 @@ public static String process(final Document document) throws RatDocumentAnalysis
document.getMetaData().setDocumentType(Document.Type.NOTICE);
}
}
-
return result;
} catch (IOException e) {
throw new RatDocumentAnalysisException(e);
diff --git a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/SelectorUtils.java b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/SelectorUtils.java
index 92c53528d..923950f24 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/SelectorUtils.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/config/exclusion/plexus/SelectorUtils.java
@@ -54,7 +54,6 @@
* .
*
*/
-
import java.io.File;
import java.util.ArrayList;
import java.util.List;
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryDocument.java b/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryDocument.java
index 0553e4339..dabc848bc 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryDocument.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryDocument.java
@@ -36,12 +36,12 @@ public class ArchiveEntryDocument extends Document {
/**
* Creates an Archive entry.
- * @param outerName the name of this entry from outside the archive.
+ * @param entryName the name of this entry from outside the archive.
* @param contents the contents of the entry.
* @param nameMatcher the name matcher to filter contents with.
*/
- public ArchiveEntryDocument(final DocumentName outerName, final byte[] contents, final DocumentNameMatcher nameMatcher) {
- super(outerName, nameMatcher);
+ public ArchiveEntryDocument(final ArchiveEntryName entryName, final byte[] contents, final DocumentNameMatcher nameMatcher) {
+ super(entryName, nameMatcher);
this.contents = contents;
}
diff --git a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
index 6d23f0616..a1f137147 100644
--- a/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
+++ b/apache-rat-tasks/src/test/java/org/apache/rat/anttasks/ReportOptionTest.java
@@ -81,7 +81,7 @@ public AntOptionsProvider() {
super(BaseAntTask.unsupportedArgs(), testPath.toFile());
}
- protected final ReportConfiguration generateConfig(List> args) {
+ protected ReportConfiguration generateConfig(final List> args) {
BuildTask task = args.get(0).getKey() == null ? new BuildTask() : new BuildTask(args.get(0).getKey());
task.setUp(args);
task.buildRule.executeTarget(task.name);
From 2905f3ac2171a0d79ea3f72d4a848b402e83ebaa Mon Sep 17 00:00:00 2001
From: Claude Warren
Date: Sun, 9 Feb 2025 00:42:59 +0100
Subject: [PATCH 36/41] RAT-98: Changes to tests for multi OS and FileDocument
change (#441)
* Changes to tests for multi OS and FileDocument change
* cleaned up test code
* Minor changes during review
---------
Co-authored-by: P. Ottlinger
---
.../rat/analysis/AnalyserFactoryTest.java | 2 +-
.../exclusion/ExclusionProcessorTest.java | 157 +++++++++++-------
.../rat/document/guesser/NoteGuesserTest.java | 25 ++-
.../rat/test/AbstractOptionsProvider.java | 88 +++++-----
4 files changed, 161 insertions(+), 111 deletions(-)
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 72ebff4be..a2814e0b4 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
@@ -137,7 +137,7 @@ public void archiveProcessingTest(ReportConfiguration.Processing archiveProcessi
@Test
public void missingFileTest() {
- final Document document = new FileDocument(
+ final Document document = new FileDocument(basedir,
new File(Resources.getExampleResource("exampleData"), "not_a_real_file"), DocumentNameMatcher.MATCHES_ALL);
Defaults defaults = Defaults.builder().build();
ReportConfiguration config = new ReportConfiguration();
diff --git a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java
index f8535a90b..85d8d9762 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/config/exclusion/ExclusionProcessorTest.java
@@ -18,11 +18,14 @@
*/
package org.apache.rat.config.exclusion;
+import java.nio.file.FileSystems;
+import java.nio.file.Path;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.apache.rat.document.DocumentNameMatcher;
import org.apache.rat.document.DocumentName;
-import org.junit.jupiter.api.BeforeEach;
-import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.io.TempDir;
import java.io.File;
@@ -31,26 +34,26 @@
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;
+import org.junit.jupiter.params.ParameterizedTest;
+import org.junit.jupiter.params.provider.Arguments;
+import org.junit.jupiter.params.provider.MethodSource;
+import org.mockito.Mockito;
import static java.lang.String.format;
import static org.assertj.core.api.Assertions.assertThat;
-import static org.assertj.core.api.Fail.fail;
+import static org.apache.rat.document.FSInfoTest.OSX;
+import static org.apache.rat.document.FSInfoTest.UNIX;
+import static org.apache.rat.document.FSInfoTest.WINDOWS;
public class ExclusionProcessorTest {
final private static DocumentNameMatcher TRUE = DocumentNameMatcher.MATCHES_ALL;
final private static DocumentNameMatcher FALSE = DocumentNameMatcher.MATCHES_NONE;
- /** The base directory for the test. */
- @TempDir
- private File basedirFile;
- private DocumentName basedir;
- @BeforeEach
- public void setup() {
- basedir = DocumentName.builder(basedirFile).build();
- }
+ @TempDir
+ private static Path tempDir;
- private void testParseExclusion(DocumentNameMatcher nameMatcher, DocumentName name, boolean expected) {
+ private void testParseExclusion(DocumentName basedir, DocumentNameMatcher nameMatcher, DocumentName name, boolean expected) {
assertThat(nameMatcher.matches(name)).as(() -> format("Failed on [%s %s]%n%s", basedir, name, dump(nameMatcher, name))).isEqualTo(expected);
}
@@ -60,48 +63,63 @@ private String dump(DocumentNameMatcher nameMatcher, DocumentName name) {
return sb.toString();
}
- private DocumentName mkName(String pth) {
- File f = new File(basedirFile, pth);
- try {
- FileUtils.cleanDirectory(basedirFile);
- FileUtils.touch(f);
- } catch (IOException e) {
- fail(e);
+ private DocumentName mkName(DocumentName baseDir, String pth) throws IOException {
+ DocumentName result = baseDir.resolve(ExclusionUtils.convertSeparator(pth, "/", baseDir.getDirectorySeparator()));
+ DocumentName mocked = Mockito.spy(result);
+
+ String fn = result.localized(FileSystems.getDefault().getSeparator());
+ File file = tempDir.resolve(fn.substring(1)).toFile();
+ File parent = file.getParentFile();
+ if (parent.exists() && !parent.isDirectory()) {
+ parent.delete();
}
- return DocumentName.builder(f).setBaseName(basedir.getBaseName()).build();
+ parent.mkdirs();
+ if (file.exists()) {
+ if (file.isDirectory()) {
+ FileUtils.deleteDirectory(file);
+ } else {
+ FileUtils.delete(file);
+ }
+ }
+ file.createNewFile();
+ Mockito.when(mocked.asFile()).thenReturn(file);
+ return mocked;
}
- @Test
- public void defaultTest() {
+ @ParameterizedTest
+ @MethodSource("getDocumentNames")
+ void defaultTest(DocumentName basedir) throws IOException {
ExclusionProcessor p = new ExclusionProcessor();
- testParseExclusion(p.getNameMatcher(basedir), mkName("hello"), true);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "hello"), true);
}
- @Test
- public void addExcludedCollectionTest() {
+ @ParameterizedTest
+ @MethodSource("getDocumentNames")
+ void addExcludedCollectionTest(DocumentName basedir) throws IOException {
ExclusionProcessor p = new ExclusionProcessor().addExcludedCollection(StandardCollection.MISC);
// "**/*~", "**/#*#", "**/.#*", "**/%*%", "**/._*"
- testParseExclusion(p.getNameMatcher(basedir), mkName("hello"), true);
- testParseExclusion(p.getNameMatcher(basedir), mkName("hello~"), false);
- testParseExclusion(p.getNameMatcher(basedir), mkName("#hello#"), false);
- testParseExclusion(p.getNameMatcher(basedir), mkName(".#hello"), false);
- testParseExclusion(p.getNameMatcher(basedir), mkName("%hello%"), false);
- testParseExclusion(p.getNameMatcher(basedir), mkName("._hello"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir,"hello"), true);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir,"hello~"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "#hello#"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, ".#hello"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "%hello%"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "._hello"), false);
}
- @Test
- public void addExcludedAndIncludedCollectionTest() {
+ @ParameterizedTest
+ @MethodSource("getDocumentNames")
+ void addExcludedAndIncludedCollectionTest(DocumentName basedir) throws IOException {
ExclusionProcessor p = new ExclusionProcessor().addExcludedCollection(StandardCollection.MISC)
.addIncludedCollection(StandardCollection.HIDDEN_FILE);
- testParseExclusion(p.getNameMatcher(basedir), mkName("hello"), true);
- testParseExclusion(p.getNameMatcher(basedir), mkName("hello~"), false);
- testParseExclusion(p.getNameMatcher(basedir), mkName("#hello#"), false);
- testParseExclusion(p.getNameMatcher(basedir), mkName(".#hello"), true);
- testParseExclusion(p.getNameMatcher(basedir), mkName("%hello%"), false);
- testParseExclusion(p.getNameMatcher(basedir), mkName("._hello"), true);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir,"hello"), true);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "hello~"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "#hello#"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, ".#hello"), true);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "%hello%"), false);
+ testParseExclusion(basedir, p.getNameMatcher(basedir), mkName(basedir, "._hello"), true);
}
- private void assertExclusions(String pattern, Map expectedMap) {
+ private void assertExclusions(DocumentName basedir, String pattern, Map expectedMap) throws IOException {
String[] paths = {"a/b/foo", "b/foo", "foo", "foo/x", "foo/x/y", "b/foo/x",
"b/foo/x/y", "a/b/foo/x", "a/b/foo/x/y"};
ExclusionProcessor p = new ExclusionProcessor().addExcludedPatterns(Collections.singletonList(pattern));
@@ -111,13 +129,13 @@ private void assertExclusions(String pattern, Map expectedMap) {
if (expected == null) {
throw new RuntimeException("Missing expected value for " + pth + " in pattern " + pattern);
}
- DocumentName dn = mkName(pth);
- testParseExclusion(pathMatcher, mkName(pth), expected);
+ testParseExclusion(basedir, pathMatcher, mkName(basedir, pth), expected);
}
}
- @Test
- public void addExcludedPatternsTest() {
+ @ParameterizedTest
+ @MethodSource("getDocumentNames")
+ void addExcludedPatternsTest(DocumentName basedir) throws IOException {
Map expectedMap = new HashMap<>();
expectedMap.put("a/b/foo", true);
@@ -129,7 +147,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", true);
expectedMap.put("a/b/foo/x", true);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("foo", expectedMap);
+ assertExclusions(basedir, "foo", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", true);
@@ -141,7 +159,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", true);
expectedMap.put("a/b/foo/x", true);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("foo/*", expectedMap);
+ assertExclusions(basedir, "foo/*", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", true);
@@ -153,7 +171,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", true);
expectedMap.put("a/b/foo/x", true);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("foo/**", expectedMap);
+ assertExclusions(basedir, "foo/**", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", true);
@@ -165,7 +183,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", true);
expectedMap.put("a/b/foo/x", true);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("*/foo", expectedMap);
+ assertExclusions(basedir, "*/foo", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", true);
@@ -177,7 +195,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", true);
expectedMap.put("a/b/foo/x", true);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("*/foo/*", expectedMap);
+ assertExclusions(basedir, "*/foo/*", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", true);
@@ -189,7 +207,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", false);
expectedMap.put("a/b/foo/x", true);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("*/foo/**", expectedMap);
+ assertExclusions(basedir, "*/foo/**", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", false);
@@ -201,7 +219,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", true);
expectedMap.put("a/b/foo/x", true);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("**/foo", expectedMap);
+ assertExclusions(basedir, "**/foo", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", true);
@@ -213,7 +231,7 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", true);
expectedMap.put("a/b/foo/x", false);
expectedMap.put("a/b/foo/x/y",true);
- assertExclusions("**/foo/*", expectedMap);
+ assertExclusions(basedir, "**/foo/*", expectedMap);
expectedMap.clear();
expectedMap.put("a/b/foo", false);
@@ -225,11 +243,12 @@ public void addExcludedPatternsTest() {
expectedMap.put("b/foo/x/y", false);
expectedMap.put("a/b/foo/x", false);
expectedMap.put("a/b/foo/x/y",false);
- assertExclusions("**/foo/**", expectedMap);
+ assertExclusions(basedir, "**/foo/**", expectedMap);
}
- @Test
- public void orTest() {
+ @ParameterizedTest
+ @MethodSource("getDocumentNames")
+ void orTest(DocumentName basedir) {
ExclusionProcessor underTest = new ExclusionProcessor();
assertThat(DocumentNameMatcher.or(Arrays.asList(TRUE, FALSE)).matches(basedir)).isTrue();
assertThat(DocumentNameMatcher.or(Arrays.asList(FALSE, TRUE)).matches(basedir)).isTrue();
@@ -237,8 +256,9 @@ public void orTest() {
assertThat(DocumentNameMatcher.or(Arrays.asList(FALSE, FALSE)).matches(basedir)).isFalse();
}
- @Test
- public void andTest() {
+ @ParameterizedTest
+ @MethodSource("getDocumentNames")
+ void andTest(DocumentName basedir) {
ExclusionProcessor underTest = new ExclusionProcessor();
assertThat(DocumentNameMatcher.and(TRUE, FALSE).matches(basedir)).isFalse();
assertThat(DocumentNameMatcher.and(FALSE, TRUE).matches(basedir)).isFalse();
@@ -246,10 +266,29 @@ public void andTest() {
assertThat(DocumentNameMatcher.and(FALSE, FALSE).matches(basedir)).isFalse();
}
- @Test
- public void notTest() {
+ @ParameterizedTest
+ @MethodSource("getDocumentNames")
+ void notTest(DocumentName basedir) {
ExclusionProcessor underTest = new ExclusionProcessor();
assertThat(DocumentNameMatcher.not(TRUE).matches(basedir)).isFalse();
assertThat(DocumentNameMatcher.not(FALSE).matches(basedir)).isTrue();
}
+
+ private static Stream getDocumentNames() {
+ List lst = new ArrayList<>();
+
+ DocumentName.Builder builder = DocumentName.builder().setName("default");
+ lst.add(Arguments.of(builder.setBaseName(builder.directorySeparator()).build()));
+
+ builder = DocumentName.builder(WINDOWS).setName("windows");
+ lst.add(Arguments.of(builder.setBaseName(builder.directorySeparator()).build()));
+
+ builder = DocumentName.builder(UNIX).setName("unix");
+ lst.add(Arguments.of(builder.setBaseName(builder.directorySeparator()).build()));
+
+ builder = DocumentName.builder(OSX).setName("osx");
+ lst.add(Arguments.of(builder.setBaseName(builder.directorySeparator()).build()));
+
+ return lst.stream();
+ }
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java b/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java
index 87d157a0e..944f9f656 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/document/guesser/NoteGuesserTest.java
@@ -22,13 +22,15 @@
import java.util.List;
import java.util.stream.Stream;
import org.apache.rat.document.DocumentName;
-import org.apache.rat.document.FSInfoTest;
import org.apache.rat.testhelpers.TestingDocument;
import org.junit.jupiter.params.ParameterizedTest;
import org.junit.jupiter.params.provider.Arguments;
import org.junit.jupiter.params.provider.MethodSource;
import static org.junit.jupiter.api.Assertions.assertEquals;
+import static org.apache.rat.document.FSInfoTest.OSX;
+import static org.apache.rat.document.FSInfoTest.UNIX;
+import static org.apache.rat.document.FSInfoTest.WINDOWS;
public class NoteGuesserTest {
@@ -42,8 +44,9 @@ public void testMatches(DocumentName testingName, boolean expected) {
private static Stream nameData() {
List lst = new ArrayList<>();
- final DocumentName linuxBaseName = DocumentName.builder(FSInfoTest.UNIX).setName("/").setBaseName("/").build();
- final DocumentName windowsBaseName = DocumentName.builder(FSInfoTest.WINDOWS).setName("\\").setBaseName("\\").build();
+ final DocumentName osxBaseName = DocumentName.builder(OSX).setName("/").setBaseName("/").build();
+ final DocumentName linuxBaseName = DocumentName.builder(UNIX).setName("/").setBaseName("/").build();
+ final DocumentName windowsBaseName = DocumentName.builder(WINDOWS).setName("\\").setBaseName("\\").build();
lst.add(Arguments.of(linuxBaseName.resolve("DEPENDENCIES"), true));
lst.add(Arguments.of(linuxBaseName.resolve("LICENSE"), true));
@@ -77,6 +80,22 @@ private static Stream nameData() {
lst.add(Arguments.of(windowsBaseName.resolve("src\\test\\README.txt"), true));
lst.add(Arguments.of(windowsBaseName.resolve("src\\test\\README.shouldFail"), false));
+ lst.add(Arguments.of(osxBaseName.resolve("DEPENDENCIES"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("LICENSE"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("LICENSE.txt"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("NOTICE"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("NOTICE.txt"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("README"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("README.txt"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/DEPENDENCIES"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/LICENSE"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/LICENSE.txt"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/NOTICE"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/NOTICE.txt"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/README"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/README.txt"), true));
+ lst.add(Arguments.of(osxBaseName.resolve("src/test/README.shouldFail"), false));
+
return lst.stream();
}
}
diff --git a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java
index 8a34245e9..6050cbbdd 100644
--- a/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java
+++ b/apache-rat-core/src/test/java/org/apache/rat/test/AbstractOptionsProvider.java
@@ -79,7 +79,7 @@
*/
public abstract class AbstractOptionsProvider implements ArgumentsProvider {
/**
- * A map of test Options to tests
+ * A map of test Options to tests.
*/
protected final Map testMap = new TreeMap<>();
/** The list of exclude args */
@@ -116,10 +116,10 @@ protected DocumentName baseName() {
/**
* Copies the test data to the specified directory.
- * @param baseDir the directory to copy the /src/test/resources to.
+ * @param baseDir the directory to copy the {@code /src/test/resources} to.
* @return the {@code baseDir} argument.
*/
- public static File setup(File baseDir) {
+ public static File setup(final File baseDir) {
try {
final File sourceDir = Resources.getResourceDirectory("OptionTools");
FileUtils.copyDirectory(sourceDir, new File(baseDir,"/src/test/resources/OptionTools"));
@@ -129,7 +129,7 @@ public static File setup(File baseDir) {
return baseDir;
}
- protected AbstractOptionsProvider(Collection unsupportedArgs, File baseDir) {
+ protected AbstractOptionsProvider(final Collection unsupportedArgs, final File baseDir) {
this.baseDir = setup(baseDir);
testMap.put("addLicense", this::addLicenseTest);
testMap.put("config", this::configTest);
@@ -185,7 +185,7 @@ protected AbstractOptionsProvider(Collection unsupportedArgs, File baseD
verifyAllMethodsDefinedAndNeeded(unsupportedArgs);
}
- private void verifyAllMethodsDefinedAndNeeded(Collection unsupportedArgs) {
+ private void verifyAllMethodsDefinedAndNeeded(final Collection unsupportedArgs) {
// verify all options have functions.
final List argNames = new ArrayList<>();
Arg.getOptions().getOptions().forEach(o -> {
@@ -215,22 +215,22 @@ private void verifyAllMethodsDefinedAndNeeded(Collection unsupportedArgs
}
@SafeVarargs
- protected final ReportConfiguration generateConfig(Pair
@@ -246,7 +247,7 @@
org.apache.maven.pluginsmaven-invoker-plugin
- ${project.build.directory}/invoker
+ ${project.basedir}/invoker_target${project.build.directory}/local-repotruesrc/it/settings.xml
@@ -262,6 +263,17 @@
+
+ maven-clean-plugin
+
+
+
+ invoker_target
+ false
+
+
+
+ org.apache.maven.pluginsmaven-checkstyle-plugin
diff --git a/apache-rat-plugin/src/it/CustomLicense/.rat/customConfig.xml b/apache-rat-plugin/src/it/CustomLicense/.rat/customConfig.xml
new file mode 100644
index 000000000..9f0ab7fb9
--- /dev/null
+++ b/apache-rat-plugin/src/it/CustomLicense/.rat/customConfig.xml
@@ -0,0 +1,17 @@
+
+
+
+ "
+
+
+
+
+ Attribution-NonCommercial-NoDerivatives
+
+
+
+
+
+
+
diff --git a/apache-rat-plugin/src/it/CustomLicense/pom.xml b/apache-rat-plugin/src/it/CustomLicense/pom.xml
index 4a03c4872..474872128 100644
--- a/apache-rat-plugin/src/it/CustomLicense/pom.xml
+++ b/apache-rat-plugin/src/it/CustomLicense/pom.xml
@@ -27,31 +27,13 @@
apache-rat-plugin@pom.version@
- false
-
-
- CC
- Creative Commons
-
-
-
-
- CC
- CC-BY-NC-ND
-
- Creative Commons Attribution-NonCommercial-NoDerivatives 4.0 International
-
- Attribution-NonCommercial-NoDerivatives
-
-
-
-
- CC
-
-
+ xml
+ .rat/customConfig.xml
+
+ .rat/**pom.xmlinvoker.properties
-
+
diff --git a/apache-rat-plugin/src/it/RAT-268/pom.xml b/apache-rat-plugin/src/it/RAT-268/pom.xml
index 2084bef08..9a42f6d02 100644
--- a/apache-rat-plugin/src/it/RAT-268/pom.xml
+++ b/apache-rat-plugin/src/it/RAT-268/pom.xml
@@ -33,12 +33,12 @@
apache-rat-plugin@pom.version@
-
- STANDARDS:0
-
-
+
+ STANDARDS:0
+
+ **/src.apt
-
+
diff --git a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
index d9d5a3022..533cdaff8 100644
--- a/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
+++ b/apache-rat-plugin/src/test/java/org/apache/rat/mp/RatCheckMojoTest.java
@@ -50,7 +50,6 @@
import org.apache.rat.testhelpers.XmlUtils;
import org.junit.jupiter.api.AfterAll;
import org.junit.jupiter.api.Assertions;
-import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
import org.junit.jupiter.api.condition.EnabledOnOs;
import org.junit.jupiter.api.condition.OS;
@@ -246,7 +245,6 @@ void it3() throws Exception {
/**
* Tests defining licenses in configuration
*/
- @Disabled("Disabled until gitignore processing is correct")
@Test
void it5() throws Exception {
final RatCheckMojo mojo = newRatMojo("it5");
@@ -352,7 +350,6 @@ void rat343() throws Exception {
/**
* Tests verifying gitignore parsing
*/
- @Disabled("Disabled until gitignore processing is correct")
@Test
void rat335() throws Exception {
final RatCheckMojo mojo = newRatMojo("RAT-335");
@@ -439,7 +436,6 @@ void rat335() throws Exception {
* So for this test we must create such a file which is specific for the current
* working directory.
*/
- @Disabled("Disabled until gitignore processing is correct")
@Test
void rat362() throws Exception {
final RatCheckMojo mojo = newRatMojo("RAT-362");
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/.classpath b/apache-rat-plugin/src/test/resources/unit/RAT-107/.classpath
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/.classpath
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/.project b/apache-rat-plugin/src/test/resources/unit/RAT-107/.project
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/.project
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/.settings/dummy b/apache-rat-plugin/src/test/resources/unit/RAT-107/.settings/dummy
new file mode 100644
index 000000000..e69de29bb
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/dummy.ipr b/apache-rat-plugin/src/test/resources/unit/RAT-107/dummy.ipr
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/dummy.ipr
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.classpath b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.classpath
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.classpath
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.project b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.project
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.project
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.settings/dummy b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/.settings/dummy
new file mode 100644
index 000000000..e69de29bb
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.iml b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.iml
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.iml
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.ipr b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.ipr
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.ipr
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.iws b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.iws
new file mode 100644
index 000000000..b77e339f2
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-107/submodule/dummy.iws
@@ -0,0 +1 @@
+This file intentionally has no Apache License Header.
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-335/.gitignore
new file mode 100644
index 000000000..8855fa805
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335/.gitignore
@@ -0,0 +1,7 @@
+*.md
+
+# This makes it ignore dir3/dir3.log and dir3/file3.log
+*.log
+
+# This makes it "unignore" dir3/file3.log
+!file*.log
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/.gitignore
new file mode 100644
index 000000000..26fd5c956
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/.gitignore
@@ -0,0 +1,3 @@
+*.txt
+!dir1.md
+file1.log
\ No newline at end of file
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/dir1.txt b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/dir1.txt
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/dir1.txt
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/file1.log b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/file1.log
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir1/file1.log
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/dir2/dir2.md b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir2/dir2.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir2/dir2.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/dir3/dir3.log b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir3/dir3.log
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335/dir3/dir3.log
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/invoker.properties b/apache-rat-plugin/src/test/resources/unit/RAT-335/invoker.properties
deleted file mode 100644
index 6e8c3479e..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-335/invoker.properties
+++ /dev/null
@@ -1,16 +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.
-
-invoker.goals = clean apache-rat:check
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-335/root.md b/apache-rat-plugin/src/test/resources/unit/RAT-335/root.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-335/root.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362/.gitignore b/apache-rat-plugin/src/test/resources/unit/RAT-362/.gitignore
new file mode 100644
index 000000000..4912996bc
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-362/.gitignore
@@ -0,0 +1,2 @@
+/foo.md
+target
\ No newline at end of file
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362/foo.md b/apache-rat-plugin/src/test/resources/unit/RAT-362/foo.md
new file mode 100644
index 000000000..a31cbc897
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/RAT-362/foo.md
@@ -0,0 +1 @@
+File without a valid license
diff --git a/apache-rat-plugin/src/test/resources/unit/RAT-362/invoker.properties b/apache-rat-plugin/src/test/resources/unit/RAT-362/invoker.properties
deleted file mode 100644
index 6e8c3479e..000000000
--- a/apache-rat-plugin/src/test/resources/unit/RAT-362/invoker.properties
+++ /dev/null
@@ -1,16 +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.
-
-invoker.goals = clean apache-rat:check
diff --git a/apache-rat-plugin/src/test/resources/unit/it5/.bzrignore b/apache-rat-plugin/src/test/resources/unit/it5/.bzrignore
deleted file mode 100644
index f59acc081..000000000
--- a/apache-rat-plugin/src/test/resources/unit/it5/.bzrignore
+++ /dev/null
@@ -1,5 +0,0 @@
-## RAT-171: Add rubbish and ensure that the plugin behaves properly
-DoesNotExistAtALL/**
-*\IllegalStuffNotExisting
-Lets-See*+?!OrWhat
-\\nDoesThatWorkAsWell\/
diff --git a/apache-rat-plugin/src/test/resources/unit/it5/.rat/customConfig.xml b/apache-rat-plugin/src/test/resources/unit/it5/.rat/customConfig.xml
new file mode 100644
index 000000000..6eea4db67
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/it5/.rat/customConfig.xml
@@ -0,0 +1,23 @@
+
+
+
+ "
+ "
+
+
+
+ Attribution-NonCommercial-NoDerivatives
+
+
+
+ Yet another license
+
+
+
+
+
+
+
+
diff --git a/apache-rat-plugin/src/test/resources/unit/it5/pom.xml b/apache-rat-plugin/src/test/resources/unit/it5/pom.xml
index 9cb1327b1..474872128 100644
--- a/apache-rat-plugin/src/test/resources/unit/it5/pom.xml
+++ b/apache-rat-plugin/src/test/resources/unit/it5/pom.xml
@@ -1,8 +1,24 @@
+
4.0.0
- org.codehaus.mojo.rat.test
- it1
+ org.apache.rat.test
+ custom-license1.0
@@ -12,84 +28,12 @@
@pom.version@xml
-
-
- YAL
- Yet another license
-
-
- YAL
-
-
- MyLicense
- YAL
- Yet Another License
-
-
- YAL
- CpyrT
- Copyright with tags
-
-
- 1990
- 1991
- foo
-
-
-
- YAL
- RegxT
- Regex with tag
-
- regex tag
-
-
- YAL
- SpdxT
- Spdx with tag
-
- spxd-tag
-
-
- YAL
- TextT
- Text with tag
-
- text-tag
-
-
- YAL
- Not
- Not testing
-
-
- not test text
-
-
-
- YAL
- All
- All testing
-
-
- all test text
- all spdx text
-
-
-
- YAL
- Any
- Any testing
-
-
- any test text
- any spdx text
-
-
-
-
- src.apt
-
+ .rat/customConfig.xml
+
+ .rat/**
+ pom.xml
+ invoker.properties
+
diff --git a/apache-rat-plugin/src/test/resources/unit/it5/src/main/java/nl/basjes/something/Something.java b/apache-rat-plugin/src/test/resources/unit/it5/src/main/java/nl/basjes/something/Something.java
new file mode 100644
index 000000000..4a7f38d95
--- /dev/null
+++ b/apache-rat-plugin/src/test/resources/unit/it5/src/main/java/nl/basjes/something/Something.java
@@ -0,0 +1,26 @@
+/*
+ * ***********************************************************************
+ * Ok, this file is really Apache _ licensed but it has a fake header
+ * that does not match the Apache rules to test custom license validation.
+ * ***********************************************************************
+ *
+ * Something toolkit
+ * Copyright (C) 2019-2024 Niels Basjes
+ *
+ * This work is licensed under the Creative Commons
+ * Attribution-NonCommercial-NoDerivatives 4.0 International License.
+ *
+ * You may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ * https://creativecommons.org/licenses/by-nc-nd/4.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.
+ */
+package nl.basjes.something;
+
+public class Something {
+ private static final String something = "No real code";
+}
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 6805f0069..4e751c493 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -72,6 +72,9 @@ The type attribute can be one of:
-->
+
+ Report skipped/excluded files and integrate testing of inclusion-exclusion and DocumentNames to work under Unix, Windows and Mac.
+
Integrate Creadur RAT into the updated develocity.apache.org instance.
From fd1202b1f859e13b89009287c2fd491ce3969d98 Mon Sep 17 00:00:00 2001
From: "P. Ottlinger"
Date: Thu, 13 Feb 2025 17:24:18 +0100
Subject: [PATCH 41/41] RAT-98: Fix javadoc
---
.../src/main/java/org/apache/rat/document/DocumentName.java | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java
index 5e41156af..dfe6d0572 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/document/DocumentName.java
@@ -40,7 +40,7 @@
import org.apache.commons.lang3.tuple.Pair;
/**
- * The name for a document. The {@code DocumentName} is an immutable structure that handles all the intricacies of file
+ * The name for a document. The {@code DocumentName} is an immutable structure that handles all the intricacies of file
* naming on various operating systems. DocumentNames have several components:
*
*
{@code root} - where in the file system the name starts (e.g C: on windows). May be empty but not null.
@@ -94,7 +94,7 @@ public static Builder builder(final FileSystem fileSystem) {
}
/**
- * Creates a builder from a File. The {@link #baseName} is set to the file name if it is a directory otherwise
+ * Creates a builder from a File. The {@link #baseName} is set to the file name if it is a directory otherwise
* it is set to the directory containing the file.
* @param file The file to set defaults from.
* @return the builder.