This is an automated email from the ASF dual-hosted git repository. ggregory pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/commons-io.git
The following commit(s) were added to refs/heads/master by this push: new 4d1ded4b Add PathMatcherFileFilter to adapt java.nio.file.PathMatcher new c3471687 Merge branch 'master' of https://gitbox.apache.org/repos/asf/commons-io.git 4d1ded4b is described below commit 4d1ded4b111e25ffea2fbe3c02b4c705cd06d2d0 Author: Gary Gregory <garydgreg...@gmail.com> AuthorDate: Fri Jun 30 00:02:07 2023 -0400 Add PathMatcherFileFilter to adapt java.nio.file.PathMatcher - MagicNumberFileFilter.accept(Path, BasicFileAttributes) doesn't its byteOffset before reading. - Move fixes into first changes section --- src/changes/changes.xml | 24 +++++++---- .../io/filefilter/MagicNumberFileFilter.java | 1 + .../io/filefilter/PathMatcherFileFilter.java | 50 ++++++++++++++++++++++ .../commons/io/filefilter/AbstractFilterTest.java | 22 +++++++--- .../commons/io/filefilter/FileFilterTest.java | 45 ++++++++++--------- .../io/filefilter/PathMatcherFileFilterTest.java | 50 ++++++++++++++++++++++ .../io/filefilter/WildcardFileFilterTest.java | 3 +- 7 files changed, 155 insertions(+), 40 deletions(-) diff --git a/src/changes/changes.xml b/src/changes/changes.xml index 1ce68660..81a4f784 100644 --- a/src/changes/changes.xml +++ b/src/changes/changes.xml @@ -48,6 +48,19 @@ The <action> type attribute can be add,update,fix,remove. <body> <release version="2.14.0" date="2023-MM-DD" description="Java 8 required."> + <!-- FIX --> + <action dev="ggregory" type="fix" issue="IO-799" due-to="Jeroen van der Vegt, Gary Gregory"> + ReaderInputStream.read() throws an exception instead of returning -1 when called again after returning -1. + </action> + <action dev="ggregory" type="fix" issue="IO-804" due-to="Elliotte Rusty Harold, Gary Gregory"> + FileUtils.forceMkdirParent() Javadoc is likely incorrect. + </action> + <action dev="ggregory" type="fix" due-to="step-security-bot, Gary Gregory"> + [StepSecurity] ci: Harden GitHub Actions #461. + </action> + <action dev="ggregory" type="fix" due-to="Gary Gregory"> + MagicNumberFileFilter.accept(Path, BasicFileAttributes) doesn't its byteOffset before reading. + </action> <!-- ADD --> <action dev="ggregory" type="add" due-to="Gary Gregory"> Add DeferredFileOutputStream.getPath(). @@ -82,15 +95,8 @@ The <action> type attribute can be add,update,fix,remove. <action dev="ggregory" type="add" due-to="Gary Gregory"> IOFileFilter now also extends java.nio.file.PathMatcher. </action> - <!-- FIX --> - <action dev="ggregory" type="fix" issue="IO-799" due-to="Jeroen van der Vegt, Gary Gregory"> - ReaderInputStream.read() throws an exception instead of returning -1 when called again after returning -1. - </action> - <action dev="ggregory" type="fix" issue="IO-804" due-to="Elliotte Rusty Harold, Gary Gregory"> - FileUtils.forceMkdirParent() Javadoc is likely incorrect. - </action> - <action dev="ggregory" type="fix" due-to="step-security-bot, Gary Gregory"> - [StepSecurity] ci: Harden GitHub Actions #461. + <action dev="ggregory" type="add" due-to="Gary Gregory"> + Add PathMatcherFileFilter to adapt java.nio.file.PathMatcher. </action> <!-- UPDATE --> </release> diff --git a/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java index e7743408..1793ef2a 100644 --- a/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java +++ b/src/main/java/org/apache/commons/io/filefilter/MagicNumberFileFilter.java @@ -293,6 +293,7 @@ public class MagicNumberFileFilter extends AbstractFileFilter implements Seriali try { try (FileChannel fileChannel = FileChannel.open(file)) { final ByteBuffer byteBuffer = ByteBuffer.allocate(this.magicNumbers.length); + fileChannel.position(byteOffset); final int read = fileChannel.read(byteBuffer); if (read != magicNumbers.length) { return FileVisitResult.TERMINATE; diff --git a/src/main/java/org/apache/commons/io/filefilter/PathMatcherFileFilter.java b/src/main/java/org/apache/commons/io/filefilter/PathMatcherFileFilter.java new file mode 100644 index 00000000..a36c6879 --- /dev/null +++ b/src/main/java/org/apache/commons/io/filefilter/PathMatcherFileFilter.java @@ -0,0 +1,50 @@ +/* + * 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.commons.io.filefilter; + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.PathMatcher; + +/** + * Delegates matching to a {@link PathMatcher}. + * + * @since 2.14.0 + */ +public class PathMatcherFileFilter extends AbstractFileFilter { + + private final PathMatcher pathMatcher; + + /** + * Constructs a new instance to perform matching with a PathMatcher. + * + * @param pathMatcher The PathMatcher delegate. + */ + public PathMatcherFileFilter(final PathMatcher pathMatcher) { + this.pathMatcher = pathMatcher; + } + + @Override + public boolean accept(File file) { + return file != null && matches(file.toPath()); + } + @Override + public boolean matches(final Path path) { + return pathMatcher.matches(path); + } +} diff --git a/src/test/java/org/apache/commons/io/filefilter/AbstractFilterTest.java b/src/test/java/org/apache/commons/io/filefilter/AbstractFilterTest.java index 3014b315..ca6f8874 100644 --- a/src/test/java/org/apache/commons/io/filefilter/AbstractFilterTest.java +++ b/src/test/java/org/apache/commons/io/filefilter/AbstractFilterTest.java @@ -24,6 +24,7 @@ import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; +import java.nio.file.attribute.BasicFileAttributes; import org.apache.commons.io.IOCase; import org.junit.jupiter.api.io.TempDir; @@ -43,7 +44,7 @@ public class AbstractFilterTest { @TempDir public File temporaryFolder; - void assertFiltering(final IOFileFilter filter, final File file, final boolean expected) { + void assertFiltering(final IOFileFilter filter, final File file, final boolean expected) throws IOException { // Note. This only tests the (File, String) version if the parent of // the File passed in is not null assertEquals(expected, filter.accept(file), "Filter(File) " + filter.getClass().getName() + " not " + expected + " for " + file); @@ -51,6 +52,13 @@ public class AbstractFilterTest { if (file != null && file.getParentFile() != null) { assertEquals(expected, filter.accept(file.getParentFile(), file.getName()), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for " + file); + final Path path = file.toPath(); + assertEquals(expected, filter.accept(path, null) != FileVisitResult.TERMINATE, filter::toString); + if (Files.isRegularFile(path)) { + assertEquals(expected, filter.accept(path, Files.readAttributes(path, BasicFileAttributes.class)) != FileVisitResult.TERMINATE, + filter::toString); + } + assertEquals(expected, filter.matches(path), filter::toString); } else if (file == null) { assertEquals(expected, filter.accept(null), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for null"); assertEquals(expected, filter.matches(null), "Filter(File, String) " + filter.getClass().getName() + " not " + expected + " for null"); @@ -63,7 +71,7 @@ public class AbstractFilterTest { // the File passed in is not null final FileVisitResult expectedFileVisitResult = AbstractFileFilter.toDefaultFileVisitResult(expected); assertEquals(expectedFileVisitResult, filter.accept(path, null), - "Filter(Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for " + path); + "Filter(Path) " + filter.getClass().getName() + " not " + expectedFileVisitResult + " for " + path); if (path != null && path.getParent() != null) { assertEquals(expectedFileVisitResult, filter.accept(path, null), @@ -79,7 +87,7 @@ public class AbstractFilterTest { assertNotNull(filter.toString()); } - void assertFooBarFileFiltering(IOFileFilter filter) { + void assertFooBarFileFiltering(IOFileFilter filter) throws IOException { assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); @@ -89,7 +97,7 @@ public class AbstractFilterTest { assertFiltering(filter, new File("bar").toPath(), true); assertFiltering(filter, new File("fred").toPath(), false); - filter = new NameFileFilter(new String[] {"foo", "bar"}, IOCase.SENSITIVE); + filter = new NameFileFilter(new String[] { "foo", "bar" }, IOCase.SENSITIVE); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), false); @@ -99,7 +107,7 @@ public class AbstractFilterTest { assertFiltering(filter, new File("FOO").toPath(), false); assertFiltering(filter, new File("BAR").toPath(), false); - filter = new NameFileFilter(new String[] {"foo", "bar"}, IOCase.INSENSITIVE); + filter = new NameFileFilter(new String[] { "foo", "bar" }, IOCase.INSENSITIVE); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), true); @@ -109,7 +117,7 @@ public class AbstractFilterTest { assertFiltering(filter, new File("FOO").toPath(), true); assertFiltering(filter, new File("BAR").toPath(), true); - filter = new NameFileFilter(new String[] {"foo", "bar"}, IOCase.SYSTEM); + filter = new NameFileFilter(new String[] { "foo", "bar" }, IOCase.SYSTEM); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), WINDOWS); @@ -119,7 +127,7 @@ public class AbstractFilterTest { assertFiltering(filter, new File("FOO").toPath(), WINDOWS); assertFiltering(filter, new File("BAR").toPath(), WINDOWS); - filter = new NameFileFilter(new String[] {"foo", "bar"}, null); + filter = new NameFileFilter(new String[] { "foo", "bar" }, null); assertFiltering(filter, new File("foo"), true); assertFiltering(filter, new File("bar"), true); assertFiltering(filter, new File("FOO"), false); diff --git a/src/test/java/org/apache/commons/io/filefilter/FileFilterTest.java b/src/test/java/org/apache/commons/io/filefilter/FileFilterTest.java index 9aa39b72..858c4a19 100644 --- a/src/test/java/org/apache/commons/io/filefilter/FileFilterTest.java +++ b/src/test/java/org/apache/commons/io/filefilter/FileFilterTest.java @@ -29,6 +29,7 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.FileFilter; import java.io.FilenameFilter; +import java.io.IOException; import java.io.OutputStream; import java.nio.charset.StandardCharsets; import java.nio.file.FileVisitResult; @@ -153,7 +154,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testAnd() { + public void testAnd() throws IOException { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(trueFilter.and(trueFilter), new File("foo.test"), true); @@ -163,7 +164,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testAnd2() { + public void testAnd2() throws IOException { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(new AndFileFilter(trueFilter, trueFilter), new File("foo.test"), true); @@ -181,7 +182,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testAndArray() { + public void testAndArray() throws IOException { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(new AndFileFilter(trueFilter, trueFilter, trueFilter), new File("foo.test"), true); @@ -252,7 +253,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testDelegateFileFilter() { + public void testDelegateFileFilter() throws IOException { final OrFileFilter orFilter = new OrFileFilter(); final File testFile = new File("test.txt"); @@ -276,7 +277,7 @@ public class FileFilterTest extends AbstractFilterTest { @SuppressWarnings("deprecation") @Test - public void testDeprecatedWildcard() { + public void testDeprecatedWildcard() throws IOException { IOFileFilter filter = new WildcardFilter("*.txt"); final List<String> patternList = Arrays.asList("*.txt", "*.xml", "*.gif"); final IOFileFilter listFilter = new WildcardFilter(patternList); @@ -355,7 +356,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testDirectory() { + public void testDirectory() throws IOException { // XXX: This test presumes the current working dir is the base dir of the source checkout. final IOFileFilter filter = new DirectoryFileFilter(); @@ -432,7 +433,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testFalse() { + public void testFalse() throws IOException { final IOFileFilter filter = FileFilterUtils.falseFileFilter(); assertFiltering(filter, new File("foo.test"), false); assertFiltering(filter, new File("foo.test").toPath(), false); @@ -447,13 +448,13 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testFileEqualsFilter() { + public void testFileEqualsFilter() throws IOException { assertFooBarFileFiltering( new FileEqualsFileFilter(new File("foo")).or(new FileEqualsFileFilter(new File("bar")))); } @Test - public void testFileFilterUtils_and() { + public void testFileFilterUtils_and() throws IOException { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; assertFiltering(FileFilterUtils.and(trueFilter, trueFilter, trueFilter), new File("foo.test"), true); @@ -463,7 +464,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testFileFilterUtils_or() { + public void testFileFilterUtils_or() throws IOException { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; final File testFile = new File("foo.test"); @@ -474,7 +475,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testFiles() { + public void testFiles() throws IOException { // XXX: This test presumes the current working dir is the base dir of the source checkout. final IOFileFilter filter = FileFileFilter.INSTANCE; @@ -700,7 +701,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testHidden() { + public void testHidden() throws IOException { final File hiddenDirFile = new File(SVN_DIR_NAME); final Path hiddenDirPath = hiddenDirFile.toPath(); if (hiddenDirFile.exists()) { @@ -797,8 +798,6 @@ public class FileFilterTest extends AbstractFilterTest { assertFiltering(filter, dir, false); } - // ----------------------------------------------------------------------- - @Test public void testMagicNumberFileFilterString() throws Exception { final byte[] classFileMagicNumber = {(byte) 0xCA, (byte) 0xFE, (byte) 0xBA, (byte) 0xBE}; @@ -1037,7 +1036,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testNameFilter() { + public void testNameFilter() throws IOException { assertFooBarFileFiltering(new NameFileFilter("foo", "bar")); } @@ -1061,7 +1060,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testNegate() { + public void testNegate() throws IOException { final IOFileFilter filter = FileFilterUtils.notFileFilter(FileFilterUtils.trueFileFilter()); assertFiltering(filter, new File("foo.test"), false); assertFiltering(filter, new File("foo"), false); @@ -1077,7 +1076,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testOr() { + public void testOr() throws IOException { final IOFileFilter trueFilter = TrueFileFilter.INSTANCE; final IOFileFilter falseFilter = FalseFileFilter.INSTANCE; final File testFile = new File("foo.test"); @@ -1124,13 +1123,13 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testPathEqualsFilter() { + public void testPathEqualsFilter() throws IOException { assertFooBarFileFiltering( new PathEqualsFileFilter(Paths.get("foo")).or(new PathEqualsFileFilter(Paths.get("bar")))); } @Test - public void testPrefix() { + public void testPrefix() throws IOException { IOFileFilter filter = new PrefixFileFilter("foo", "bar"); final File testFile = new File("test"); final Path testPath = testFile.toPath(); @@ -1194,7 +1193,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testPrefixCaseInsensitive() { + public void testPrefixCaseInsensitive() throws IOException { IOFileFilter filter = new PrefixFileFilter(new String[] {"foo", "bar"}, IOCase.INSENSITIVE); assertFiltering(filter, new File("foo.test1"), true); @@ -1323,7 +1322,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testSuffix() { + public void testSuffix() throws IOException { IOFileFilter filter = new SuffixFileFilter("tes", "est"); final File testFile = new File("test"); final Path testPath = testFile.toPath(); @@ -1380,7 +1379,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testSuffixCaseInsensitive() { + public void testSuffixCaseInsensitive() throws IOException { IOFileFilter filter = new SuffixFileFilter(new String[] {"tes", "est"}, IOCase.INSENSITIVE); assertFiltering(filter, new File("foo.tes"), true); @@ -1414,7 +1413,7 @@ public class FileFilterTest extends AbstractFilterTest { } @Test - public void testTrue() { + public void testTrue() throws IOException { final IOFileFilter filter = FileFilterUtils.trueFileFilter(); assertFiltering(filter, new File("foo.test"), true); assertFiltering(filter, new File("foo"), true); diff --git a/src/test/java/org/apache/commons/io/filefilter/PathMatcherFileFilterTest.java b/src/test/java/org/apache/commons/io/filefilter/PathMatcherFileFilterTest.java new file mode 100644 index 00000000..ce794115 --- /dev/null +++ b/src/test/java/org/apache/commons/io/filefilter/PathMatcherFileFilterTest.java @@ -0,0 +1,50 @@ +/* + * 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.commons.io.filefilter; + +import static org.junit.jupiter.api.Assertions.assertTrue; + +import java.io.File; +import java.io.IOException; +import java.nio.file.FileSystems; + +import org.junit.jupiter.api.Test; + +/** + * Tests {@link PathMatcherFileFilter}. + */ +public class PathMatcherFileFilterTest extends AbstractFilterTest { + + @Test + public void testGlob() throws IOException { + @SuppressWarnings("resource") + final IOFileFilter filter = new PathMatcherFileFilter(FileSystems.getDefault().getPathMatcher("glob:*.txt")); + final File file1 = new File("log.txt"); + final File file2 = new File("log.TXT"); + // + assertTrue(filter.accept(file1)); + assertTrue(filter.accept(file2)); + assertTrue(filter.accept(file1.getParentFile(), file1.getName())); + assertTrue(filter.accept(file2.getParentFile(), file2.getName())); + assertFiltering(filter, file1, true); + assertFiltering(filter, file2, true); + assertFiltering(filter, file1.toPath(), true); + assertFiltering(filter, file2.toPath(), true); + } + +} diff --git a/src/test/java/org/apache/commons/io/filefilter/WildcardFileFilterTest.java b/src/test/java/org/apache/commons/io/filefilter/WildcardFileFilterTest.java index af3755ae..44ee1fa9 100644 --- a/src/test/java/org/apache/commons/io/filefilter/WildcardFileFilterTest.java +++ b/src/test/java/org/apache/commons/io/filefilter/WildcardFileFilterTest.java @@ -23,6 +23,7 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import static org.junit.jupiter.api.Assertions.assertTrue; import java.io.File; +import java.io.IOException; import java.nio.file.FileVisitResult; import java.nio.file.Path; import java.util.Arrays; @@ -34,7 +35,7 @@ import org.junit.jupiter.api.Test; public class WildcardFileFilterTest extends AbstractFilterTest { @Test - public void testWildcard() { + public void testWildcard() throws IOException { IOFileFilter filter = new WildcardFileFilter("*.txt"); assertFiltering(filter, new File("log.txt"), true); assertFiltering(filter, new File("log.TXT"), false);