This is an automated email from the ASF dual-hosted git repository.
claude pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/creadur-rat.git
The following commit(s) were added to refs/heads/master by this push:
new 3529867e RAT-98: Added FSInfo to handle file system differences (#421)
3529867e is described below
commit 3529867ef406cca7e384519ed8dd5a2480cb2271
Author: Claude Warren <[email protected]>
AuthorDate: Tue Jan 28 00:09:44 2025 +0100
RAT-98: Added FSInfo to handle file system differences (#421)
* Added FSInfo to handle file system differences
* updated spotbugs
* added more descriptive failure messages
* modified test output
* fixed FileListWalker
* reduced logging noise
* Minor javadoc fixes
* Apply minor cleanups and javadoc fixes
* cleaned up as per review
* fixed rebase issue
---------
Co-authored-by: P. Ottlinger <[email protected]>
---
apache-rat-core/pom.xml | 5 +
.../src/it/java/org/apache/rat/ReportTest.java | 2 +-
.../src/main/java/org/apache/rat/api/Document.java | 12 +-
.../rat/config/exclusion/ExclusionUtils.java | 26 +-
.../rat/config/exclusion/plexus/MatchPattern.java | 8 +-
.../rat/config/exclusion/plexus/MatchPatterns.java | 5 +-
.../org/apache/rat/document/ArchiveEntryName.java | 74 +++
.../java/org/apache/rat/document/DocumentName.java | 567 ++++++++++++++-------
.../apache/rat/document/DocumentNameMatcher.java | 26 +-
.../java/org/apache/rat/document/FileDocument.java | 18 +-
.../java/org/apache/rat/walker/ArchiveWalker.java | 20 +-
.../java/org/apache/rat/walker/FileListWalker.java | 26 +-
.../java/org/apache/rat/OptionCollectionTest.java | 12 +-
.../apache/rat/analysis/AnalyserFactoryTest.java | 4 +-
.../config/exclusion/ExclusionProcessorTest.java | 8 +-
.../rat/config/exclusion/FileProcessorTest.java | 3 +-
.../org/apache/rat/document/DocumentNameTest.java | 315 ++++++++----
.../java/org/apache/rat/document/FSInfoTest.java | 58 +++
.../rat/document/guesser/NoteGuesserTest.java | 7 +-
.../apache/rat/test/AbstractOptionsProvider.java | 14 +-
.../apache/rat/testhelpers/TestingDocument.java | 7 +-
.../org/apache/rat/walker/FileListWalkerTest.java | 12 +-
pom.xml | 12 +-
23 files changed, 878 insertions(+), 363 deletions(-)
diff --git a/apache-rat-core/pom.xml b/apache-rat-core/pom.xml
index 8ac00d1e..844a7efc 100644
--- a/apache-rat-core/pom.xml
+++ b/apache-rat-core/pom.xml
@@ -281,5 +281,10 @@
<artifactId>groovy-all</artifactId>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.jimfs</groupId>
+ <artifactId>jimfs</artifactId>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</project>
diff --git a/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java
b/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java
index b58c6732..16bc908b 100644
--- a/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java
+++ b/apache-rat-core/src/it/java/org/apache/rat/ReportTest.java
@@ -163,7 +163,7 @@ public class ReportTest {
@Override
public void report(Document document) {
if (!document.isIgnored()) {
- String[] tokens =
document.getName().tokenize(document.getName().localized());
+ String[] tokens =
DocumentName.FSInfo.getDefault().tokenize(document.getName().localized());
results.add(Arguments.of(tokens[1], document));
}
}
diff --git a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java
b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java
index 3e29eb35..0dbfa10c 100644
--- a/apache-rat-core/src/main/java/org/apache/rat/api/Document.java
+++ b/apache-rat-core/src/main/java/org/apache/rat/api/Document.java
@@ -52,7 +52,7 @@ public abstract class Document implements
Comparable<Document> {
}
/** The path matcher used by this document */
- protected final DocumentNameMatcher nameExcluder;
+ protected final DocumentNameMatcher nameMatcher;
/** The metadata for this document */
private final MetaData metaData;
/** The fully qualified name of this document */
@@ -61,11 +61,11 @@ public abstract class Document implements
Comparable<Document> {
/**
* Creates an instance.
* @param name the native NameSet of the resource.
- * @param nameExcluder the document name matcher to filter
directories/files.
+ * @param nameMatcher the document name matcher to filter
directories/files.
*/
- protected Document(final DocumentName name, final DocumentNameMatcher
nameExcluder) {
+ protected Document(final DocumentName name, final DocumentNameMatcher
nameMatcher) {
this.name = name;
- this.nameExcluder = nameExcluder;
+ this.nameMatcher = nameMatcher;
this.metaData = new MetaData();
}
@@ -81,8 +81,8 @@ public abstract class Document implements
Comparable<Document> {
* Gets the file filter this document was created with.
* @return the file filter this document was created with.
*/
- public final DocumentNameMatcher getNameExcluder() {
- return nameExcluder;
+ public final DocumentNameMatcher getNameMatcher() {
+ return nameMatcher;
}
@Override
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 339ce097..7932db4f 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
@@ -62,7 +62,7 @@ public final class ExclusionUtils {
* Creates predicate that filters out comment and blank lines. Leading
spaces are removed and
* if the line then starts with a commentPrefix string it is considered a
comment and will be removed
*
- * @param commentPrefixes the list of comment prefixes
+ * @param commentPrefixes the list of comment prefixes.
* @return the Predicate that returns false for lines that start with
commentPrefixes or are empty.
*/
public static Predicate<String> commentFilter(final Iterable<String>
commentPrefixes) {
@@ -108,7 +108,7 @@ public final class ExclusionUtils {
/**
* Create a FileFilter from a PathMatcher.
* @param parent the document name for the parent of the file to be
filtered.
- * @param nameMatcher the path matcher to convert
+ * @param nameMatcher the path matcher to convert.
* @return a FileFilter.
*/
public static FileFilter asFileFilter(final DocumentName parent, final
DocumentNameMatcher nameMatcher) {
@@ -119,7 +119,7 @@ public final class ExclusionUtils {
* Creates an iterator of Strings from a file of patterns.
* Removes comment lines.
* @param patternFile the file to read.
- * @param commentFilters A predicate return true for non-comment lines
+ * @param commentFilters A predicate returning {@code true} for
non-comment lines.
* @return the iterable of Strings from the file.
*/
public static ExtendedIterator<String> asIterator(final File patternFile,
final Predicate<String> commentFilters) {
@@ -147,7 +147,7 @@ public final class ExclusionUtils {
* Creates an iterable of Strings from a file of patterns.
* Removes comment lines.
* @param patternFile the file to read.
- * @param commentFilters A predicate returning true for non-comment lines
+ * @param commentFilters A predicate returning {@code true} for
non-comment lines.
* @return the iterable of Strings from the file.
*/
public static Iterable<String> asIterable(final File patternFile, final
Predicate<String> commentFilters) {
@@ -171,9 +171,9 @@ public final class ExclusionUtils {
}
/**
- * Returns {@code true} if the file name represents a hidden file
+ * Returns {@code true} if the file name represents a hidden file.
* @param f the file to check.
- * @return true if it is the name of a hidden file.
+ * @return {@code true} if it is the name of a hidden file.
*/
public static boolean isHidden(final File f) {
String s = f.getName();
@@ -185,4 +185,18 @@ public final class ExclusionUtils {
throw new ConfigurationException(format("%s is not a valid file.",
file));
}
}
+
+ /**
+ * Tokenizes the string based on the directory separator.
+ * @param source the source to tokenize.
+ * @param from the directory separator for the source.
+ * @param to the directory separator for the result.
+ * @return the source string with the separators converted.
+ */
+ public static String convertSeparator(final String source, final String
from, final String to) {
+ if (StringUtils.isEmpty(source) || from.equals(to)) {
+ return source;
+ }
+ return String.join(to, source.split("\\Q" + from + "\\E"));
+ }
}
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 b606136a..9932376f 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
@@ -84,8 +84,8 @@ public final class MatchPattern {
} else {
result =
SelectorUtils.matchAntPathPattern(getTokenizedPathChars(), strDirs,
isCaseSensitive);
}
- if (DefaultLog.getInstance().isEnabled(Log.Level.DEBUG)) {
- DefaultLog.getInstance().debug(format("%s match %s -> %s", this,
str, result));
+ if (result && DefaultLog.getInstance().isEnabled(Log.Level.DEBUG)) {
+ DefaultLog.getInstance().debug(format("%s match %s -> true", this,
str));
}
return result;
}
@@ -117,7 +117,8 @@ public final class MatchPattern {
@Override
public String toString() {
- return Arrays.asList(tokenized).toString();
+ return Arrays.asList(tokenized)
+ .toString();
}
public String source() {
@@ -141,5 +142,4 @@ public final class MatchPattern {
}
return tokenizedNameChar;
}
-
}
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 06c4672d..0a670393 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,7 +42,10 @@ public final class MatchPatterns {
@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/main/java/org/apache/rat/document/ArchiveEntryName.java
b/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryName.java
new file mode 100644
index 00000000..99bdcc45
--- /dev/null
+++
b/apache-rat-core/src/main/java/org/apache/rat/document/ArchiveEntryName.java
@@ -0,0 +1,74 @@
+/*
+ * 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.nio.file.Path;
+import java.nio.file.Paths;
+import java.util.Collections;
+
+public class ArchiveEntryName extends DocumentName {
+ /** The name of the document that contains this entry. */
+ private final DocumentName archiveFileName;
+
+ private static DocumentName.Builder prepareBuilder(final DocumentName
archiveFileName, final String archiveEntryName) {
+ String root = archiveFileName.getName() + "#";
+ FSInfo fsInfo = new FSInfo("archiveEntry", "/", true,
Collections.singletonList(root));
+ return DocumentName.builder(fsInfo)
+ .setRoot(root)
+ .setBaseName(root + "/")
+ .setName(archiveEntryName);
+ }
+ public ArchiveEntryName(final DocumentName archiveFileName, final String
archiveEntryName) {
+ super(prepareBuilder(archiveFileName, archiveEntryName));
+ this.archiveFileName = archiveFileName;
+ }
+
+ @Override
+ public File asFile() {
+ return archiveFileName.asFile();
+ }
+
+ @Override
+ public Path asPath() {
+ return Paths.get(archiveFileName.asPath().toString(), "#",
super.asPath().toString());
+ }
+
+ @Override
+ public DocumentName resolve(final String child) {
+ return new ArchiveEntryName(this.archiveFileName,
super.resolve(child).localized());
+ }
+
+ @Override
+ public String getBaseName() {
+ return archiveFileName.getName() + "#";
+ }
+
+ @Override
+ boolean startsWithRootOrSeparator(final String candidate, final String
root, final String separator) {
+ return super.startsWithRootOrSeparator(candidate, root, separator);
+ }
+
+ @Override
+ public String localized(final String dirSeparator) {
+ String superLocal = super.localized(dirSeparator);
+ superLocal = superLocal.substring(superLocal.lastIndexOf("#") + 1);
+ return archiveFileName.localized(dirSeparator) + "#" + superLocal;
+ }
+}
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 e71bed85..d5cc1126 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
@@ -20,29 +20,34 @@ package org.apache.rat.document;
import java.io.File;
import java.io.IOException;
+import java.nio.file.FileSystem;
+import java.nio.file.FileSystems;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.Paths;
import java.util.ArrayList;
import java.util.Arrays;
-import java.util.HashSet;
import java.util.List;
import java.util.Objects;
-import java.util.Set;
+import java.util.Optional;
+import java.util.stream.Collectors;
-import org.apache.commons.io.FileUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.apache.commons.lang3.builder.CompareToBuilder;
+import org.apache.commons.lang3.builder.EqualsBuilder;
+import org.apache.commons.lang3.builder.HashCodeBuilder;
import org.apache.commons.lang3.tuple.ImmutablePair;
import org.apache.commons.lang3.tuple.Pair;
-import org.apache.rat.utils.DefaultLog;
/**
* 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:
* <ul>
- * <li>{@code root} - Where in the file system the name starts (e.g C: on
windows). May be empty but not null.</li>
+ * <li>{@code root} - where in the file system the name starts (e.g C: on
windows). May be empty but not null.</li>
* <li>{@code dirSeparator} - the separator between name segments (e.g.
"\\" on windows, "/" on linux). May not be
* empty or null.</li>
- * <li>{@code name} - The name of the file relative to the {@code root}.
May not be null. Does NOT begin with a {@code dirSeparator}</li>
- * <li>{@code baseName} - The name of a directory or file from which this
file is reported. A DocumentName with a
+ * <li>{@code name} - the name of the file relative to the {@code root}.
May not be null. Does NOT begin with a {@code dirSeparator}</li>
+ * <li>{@code baseName} - the name of a directory or file from which this
file is reported. A DocumentName with a
* {@code name} of "foo/bar/baz.txt" and a {@code baseName} of "foo" will
be reported as "bar/baz.txt". May not be null.</li>
* <li>{@code isCaseSensitive} - identifies if the underlying file system
is case-sensitive.</li>
* </ul>
@@ -51,66 +56,84 @@ import org.apache.rat.utils.DefaultLog;
* within an archive. When representing a file in an archive the baseName
is the name of the enclosing archive document.
* </p>
*/
-public final class DocumentName implements Comparable<DocumentName> {
- /** The list of all roots on the file system. */
- static final Set<String> 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<DocumentName> {
/** 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 final class DocumentName implements
Comparable<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<String> 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 final class DocumentName implements
Comparable<DocumentName> {
* @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 final class DocumentName implements
Comparable<DocumentName> {
* @return the fully qualified basename of the document.
*/
public String getBaseName() {
- return root + dirSeparator + baseName;
+ return baseName.getName();
}
/**
@@ -182,7 +228,7 @@ public final class DocumentName implements
Comparable<DocumentName> {
* @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 final class DocumentName implements
Comparable<DocumentName> {
* @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 final class DocumentName implements
Comparable<DocumentName> {
* @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 final class DocumentName implements
Comparable<DocumentName> {
* @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 final class DocumentName implements
Comparable<DocumentName> {
* @return {@code true} if the name is case-sensitive.
*/
public boolean isCaseSensitive() {
- return isCaseSensitive;
+ return fsInfo.isCaseSensitive();
}
/**
@@ -255,88 +322,239 @@ public final class DocumentName implements
Comparable<DocumentName> {
}
@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<FSInfo> {
+ /** 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<String> 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<String> 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<String> 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<String> 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 @@ public final class DocumentName implements
Comparable<DocumentName> {
* @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.
* <p>
- * 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.
* </p>
- * @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<String, String> pair = splitRoot(name, dirSeparator);
+ Pair<String, String> 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<String, String> splitRoot(final File file) {
- return splitRoot(file.getAbsolutePath(), File.separator);
- }
-
/**
* Extracts the root/name pair from a name string.
* <p>
* Package private for testing.
* </p>
* @param name the name to extract the root/name pair from.
- * @param dirSeparator the directory separator.
* @return the root/name pair.
*/
- static Pair<String, String> splitRoot(final String name, final String
dirSeparator) {
+ Pair<String, String> 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<String> 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 @@ public final class DocumentName implements
Comparable<DocumentName> {
}
/**
- * 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<String, String> pair = splitRoot(file);
+ Pair<String, String> 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 final class DocumentName implements
Comparable<DocumentName> {
* Sets the baseName.
* Will set the root if it is not set.
* <p>
- * 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.
* </p>
* @param baseName the basename to use.
* @return this.
*/
public Builder setBaseName(final String baseName) {
- Pair<String, String> 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 final class DocumentName implements
Comparable<DocumentName> {
* @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 final class DocumentName implements
Comparable<DocumentName> {
}
/**
- * 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<String, String> 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 80fe275e..6b3c31bd 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 final class DocumentNameMatcher {
/**
* 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 final class DocumentNameMatcher {
}
/**
- * A DocumentName predicate that uses MatchPatterns.
+ * A DocumentName predicate that uses {@link MatchPatterns}.
*/
public static final class MatchPatternsPredicate implements
Predicate<DocumentName> {
- /** 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 final class DocumentNameMatcher {
}
/**
- * A DocumentName predicate that uses FileFilter.
+ * A DocumentName predicate that uses {@link FileFilter}.
*/
public static final class FileFilterPredicate implements
Predicate<DocumentName> {
- /** The file filter */
+ /** The file filter. */
private final FileFilter fileFilter;
private FileFilterPredicate(final FileFilter fileFilter) {
@@ -386,11 +386,15 @@ public final class DocumentNameMatcher {
}
}
+ /**
+ * A marker interface to indicate this predicate contains a collection of
matchers.
+ */
interface CollectionPredicate extends Predicate<DocumentName> {
Iterable<DocumentNameMatcher> 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 final class DocumentNameMatcher {
* 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 3e7dec89..d7596a3e 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 class FileDocument extends Document {
SortedSet<Document> 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 d9148701..a50aa5ef 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.commons.io.IOUtils;
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 org.apache.rat.utils.DefaultLog;
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 class ArchiveWalker extends Walker {
}
/**
- * 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 @@ public class ArchiveWalker extends Walker {
public Collection<Document> getDocuments() throws RatException {
List<Document> 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 6e6c50e5..05609085 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 java.io.Reader;
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 @@ import org.apache.rat.utils.DefaultLog;
* 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 f723e5fd..c0d45c08 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.Option;
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.List;
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 class OptionCollectionTest {
@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 4e2461ce..72ebff4b 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 class AnalyserFactoryTest {
private static Stream<Arguments> archiveProcessingTestData() {
List<Arguments> 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 580d1084..f8535a90 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 class ExclusionProcessorTest {
}
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 0519cee8..92291267 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.ArrayList;
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 @@ public class FileProcessorTest {
public static Stream<Arguments> localizePatternData() {
List<Arguments> 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 def6ec44..beeeeca9 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<Arguments> resolveTestData() {
+ List<Arguments> 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<Arguments> validBuilderData() {
@@ -94,98 +262,65 @@ public class DocumentNameTest {
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<String> preserve = new HashSet<>(DocumentName.ROOTS);
- try {
- DocumentName.ROOTS.clear();
- DocumentName.ROOTS.add("C:\\");
- Pair<String, String> 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<String, String> 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<String> 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 00000000..ced9d8c6
--- /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<Arguments> 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 2abf1934..87d157a0 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.ArrayList;
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 class NoteGuesserTest {
private static Stream<Arguments> nameData() {
List<Arguments> 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 57c5a051..8a34245e 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 @@ public abstract class AbstractOptionsProvider implements
ArgumentsProvider {
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 @@ public abstract class AbstractOptionsProvider implements
ArgumentsProvider {
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 @@ public abstract class AbstractOptionsProvider implements
ArgumentsProvider {
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 c1e75668..1bd66377 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.commons.io.function.IOSupplier;
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 class TestingDocument extends Document {
}
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> 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 14ac1478..ec739f64 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.BeforeAll;
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 class FileListWalkerTest {
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 class FileListWalkerTest {
writer.flush();
System.out.flush();
}
-
- hiddenName =
DocumentName.builder(hiddenFile).setBaseName(rootName.getBaseName()).build();
}
@Test
@@ -122,10 +119,7 @@ public class FileListWalkerTest {
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 7bfceb03..4d164ecb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -217,6 +217,12 @@ agnostic home for software distribution comprehension and
audit tools.
<version>2.4.21</version>
<scope>test</scope>
</dependency>
+ <dependency>
+ <groupId>com.google.jimfs</groupId>
+ <artifactId>jimfs</artifactId>
+ <version>1.3.0</version>
+ <scope>test</scope>
+ </dependency>
</dependencies>
</dependencyManagement>
<reporting>
@@ -379,8 +385,8 @@ agnostic home for software distribution comprehension and
audit tools.
<artifactId>spotbugs-maven-plugin</artifactId>
<version>4.8.6.6</version>
<configuration>
- <!-- RAT-369: JDK21 finds 94 errors, while older releases find
fewer -->
- <maxAllowedViolations>94</maxAllowedViolations>
+ <!-- RAT-369: JDK21 finds 98 errors, while older releases find
fewer -->
+ <maxAllowedViolations>98</maxAllowedViolations>
<failOnError>true</failOnError>
<!-- we only want to see our own problems in all subpackages -->
<onlyAnalyze>org.apache.rat.-</onlyAnalyze>
@@ -489,7 +495,7 @@ agnostic home for software distribution comprehension and
audit tools.
<plugin>
<groupId>org.apache.maven.plugins</groupId>
<artifactId>maven-remote-resources-plugin</artifactId>
- <version>3.3.0</version>
+ <version>3.2.0</version>
</plugin>
<plugin>
<groupId>org.apache.maven.plugins</groupId>