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 d6877f494 Add FileAlterationObserver.Builder() and deprecate most
constructors
d6877f494 is described below
commit d6877f494fc801bf95655a73a35c15f425908c75
Author: Gary Gregory <[email protected]>
AuthorDate: Thu Oct 17 09:53:23 2024 -0400
Add FileAlterationObserver.Builder() and deprecate most constructors
---
src/changes/changes.xml | 1 +
.../commons/io/monitor/FileAlterationObserver.java | 113 ++++++++++++++--
.../commons/io/monitor/AbstractMonitorTest.java | 2 +-
.../io/monitor/FileAlterationObserverTest.java | 150 +++++++++++++++++++--
4 files changed, 245 insertions(+), 21 deletions(-)
diff --git a/src/changes/changes.xml b/src/changes/changes.xml
index 3a2e57787..cc3ed7140 100644
--- a/src/changes/changes.xml
+++ b/src/changes/changes.xml
@@ -58,6 +58,7 @@ The <action> type attribute can be add,update,fix,remove.
<action dev="ggregory" type="add" due-to="Gary
Gregory">Add a "Safe Deserialization" section to the User Guide for the
site.</action>
<action dev="ggregory" type="add" due-to="Gary
Gregory">Add IORandomAccessFile.</action>
<action dev="ggregory" type="add" due-to="Gary
Gregory">Add RandomAccessFileMode.io(String).</action>
+ <action dev="ggregory" type="add" due-to="Gary
Gregory">Add FileAlterationObserver.Builder() and deprecate most
constructors.</action>
<!-- UPDATE -->
<action dev="ggregory" type="update" due-to="Gary
Gregory">Bump org.apache.commons:commons-parent from 74 to 77 #670, #676,
#679.</action>
<action dev="ggregory" type="update" due-to="Gary
Gregory">Bump commons.bytebuddy.version from 1.15.1 to 1.15.4 #672, #673,
#685.</action>
diff --git
a/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
b/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
index 4b3289a9b..393867319 100644
--- a/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
+++ b/src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
@@ -18,6 +18,7 @@ package org.apache.commons.io.monitor;
import java.io.File;
import java.io.FileFilter;
+import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
@@ -29,6 +30,7 @@ import java.util.stream.Stream;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.IOCase;
+import org.apache.commons.io.build.AbstractOriginSupplier;
import org.apache.commons.io.comparator.NameFileComparator;
import org.apache.commons.io.filefilter.TrueFileFilter;
@@ -44,6 +46,7 @@ import org.apache.commons.io.filefilter.TrueFileFilter;
* <li>Either register the observer(s) with a {@link FileAlterationMonitor} or
run manually.</li>
* </ul>
* <h2>Basic Usage</h2> Create a {@link FileAlterationObserver} for the
directory and register the listeners:
+ *
* <pre>
* File directory = new File(FileUtils.current(), "src");
* FileAlterationObserver observer = new
FileAlterationObserver(directory);
@@ -53,6 +56,7 @@ import org.apache.commons.io.filefilter.TrueFileFilter;
* <p>
* To manually observe a directory, initialize the observer and invoked the
{@link #checkAndNotify()} method as required:
* </p>
+ *
* <pre>
* // initialize
* observer.init();
@@ -68,6 +72,7 @@ import org.apache.commons.io.filefilter.TrueFileFilter;
* <p>
* Alternatively, register the observer(s) with a {@link
FileAlterationMonitor}, which creates a new thread, invoking the observer at
the specified interval:
* </p>
+ *
* <pre>
* long interval = ...
* FileAlterationMonitor monitor = new FileAlterationMonitor(interval);
@@ -76,6 +81,7 @@ import org.apache.commons.io.filefilter.TrueFileFilter;
* ...
* monitor.stop();
* </pre>
+ *
* <h2>File Filters</h2> This implementation can monitor portions of the file
system by using {@link FileFilter}s to observe only the files and/or directories
* that are of interest. This makes it more efficient and reduces the noise
from <em>unwanted</em> file system events.
* <p>
@@ -86,6 +92,7 @@ import org.apache.commons.io.filefilter.TrueFileFilter;
* For example, to only observe 1) visible directories and 2) files with a
".java" suffix in a root directory called "src" you could set up a
* {@link FileAlterationObserver} in the following way:
* </p>
+ *
* <pre>
* // Create a FileFilter
* IOFileFilter directories = FileFilterUtils.and(
@@ -101,12 +108,12 @@ import org.apache.commons.io.filefilter.TrueFileFilter;
* observer.addListener(...);
* observer.addListener(...);
* </pre>
+ *
* <h2>FileEntry</h2>
* <p>
- * {@link FileEntry} represents the state of a file or directory, capturing
{@link File} attributes at a point in time. Custom
- * implementations of {@link FileEntry} can be used to capture additional
properties that the basic implementation does not support. The
- * {@link FileEntry#refresh(File)} method is used to determine if a file or
directory has changed since the last check and stores the current state of the
- * {@link File}'s properties.
+ * {@link FileEntry} represents the state of a file or directory, capturing
{@link File} attributes at a point in time. Custom implementations of
+ * {@link FileEntry} can be used to capture additional properties that the
basic implementation does not support. The {@link FileEntry#refresh(File)}
method is
+ * used to determine if a file or directory has changed since the last check
and stores the current state of the {@link File}'s properties.
* </p>
* <h2>Deprecating Serialization</h2>
* <p>
@@ -119,8 +126,76 @@ import org.apache.commons.io.filefilter.TrueFileFilter;
*/
public class FileAlterationObserver implements Serializable {
+ /**
+ * Builds instances of {@link FileAlterationObserver}.
+ *
+ * @since 2.18.0
+ */
+ public static final class Builder extends
AbstractOriginSupplier<FileAlterationObserver, Builder> {
+
+ private FileEntry rootEntry;
+ private FileFilter fileFilter;
+ private IOCase ioCase;
+
+ private Builder() {
+ // empty
+ }
+
+ /**
+ * Gets a new {@link FileAlterationObserver} instance.
+ */
+ @Override
+ public FileAlterationObserver get() throws IOException {
+ return new FileAlterationObserver(rootEntry != null ? rootEntry :
new FileEntry(checkOrigin().getFile()), fileFilter, toComparator(ioCase));
+ }
+
+ /**
+ * Sets the file filter or null if none.
+ *
+ * @param fileFilter file filter or null if none.
+ * @return This instance.
+ */
+ public Builder setFileFilter(final FileFilter fileFilter) {
+ this.fileFilter = fileFilter;
+ return asThis();
+ }
+
+ /**
+ * Sets what case sensitivity to use comparing file names, null means
system sensitive.
+ *
+ * @param ioCase what case sensitivity to use comparing file names,
null means system sensitive.
+ * @return This instance.
+ */
+ public Builder setIOCase(final IOCase ioCase) {
+ this.ioCase = ioCase;
+ return asThis();
+ }
+
+ /**
+ * Sets the root directory to observe.
+ *
+ * @param rootEntry the root directory to observe.
+ * @return This instance.
+ */
+ public Builder setRootEntry(final FileEntry rootEntry) {
+ this.rootEntry = rootEntry;
+ return asThis();
+ }
+
+ }
+
private static final long serialVersionUID = 1185122225658782848L;
+ /**
+ * Creates a new builder.
+ *
+ * @return a new builder.
+ * @since 2.18.0
+ */
+ public static Builder builder() {
+ return new Builder();
+ }
+
private static Comparator<File> toComparator(final IOCase ioCase) {
switch (IOCase.value(ioCase, IOCase.SYSTEM)) {
case SYSTEM:
@@ -156,7 +231,9 @@ public class FileAlterationObserver implements Serializable
{
* Constructs an observer for the specified directory.
*
* @param directory the directory to observe.
+ * @deprecated Use {@link #builder()}.
*/
+ @Deprecated
public FileAlterationObserver(final File directory) {
this(directory, null);
}
@@ -164,9 +241,11 @@ public class FileAlterationObserver implements
Serializable {
/**
* Constructs an observer for the specified directory and file filter.
*
- * @param directory the directory to observe.
+ * @param directory The directory to observe.
* @param fileFilter The file filter or null if none.
+ * @deprecated Use {@link #builder()}.
*/
+ @Deprecated
public FileAlterationObserver(final File directory, final FileFilter
fileFilter) {
this(directory, fileFilter, null);
}
@@ -174,10 +253,12 @@ public class FileAlterationObserver implements
Serializable {
/**
* Constructs an observer for the specified directory, file filter and
file comparator.
*
- * @param directory the directory to observe.
+ * @param directory The directory to observe.
* @param fileFilter The file filter or null if none.
- * @param ioCase what case sensitivity to use comparing file names,
null means system sensitive.
+ * @param ioCase What case sensitivity to use comparing file names,
null means system sensitive.
+ * @deprecated Use {@link #builder()}.
*/
+ @Deprecated
public FileAlterationObserver(final File directory, final FileFilter
fileFilter, final IOCase ioCase) {
this(new FileEntry(directory), fileFilter, ioCase);
}
@@ -185,9 +266,9 @@ public class FileAlterationObserver implements Serializable
{
/**
* Constructs an observer for the specified directory, file filter and
file comparator.
*
- * @param rootEntry the root directory to observe.
+ * @param rootEntry The root directory to observe.
* @param fileFilter The file filter or null if none.
- * @param comparator how to compare files.
+ * @param comparator How to compare files.
*/
private FileAlterationObserver(final FileEntry rootEntry, final FileFilter
fileFilter, final Comparator<File> comparator) {
Objects.requireNonNull(rootEntry, "rootEntry");
@@ -200,9 +281,9 @@ public class FileAlterationObserver implements Serializable
{
/**
* Constructs an observer for the specified directory, file filter and
file comparator.
*
- * @param rootEntry the root directory to observe.
+ * @param rootEntry The root directory to observe.
* @param fileFilter The file filter or null if none.
- * @param ioCase what case sensitivity to use comparing file names,
null means system sensitive.
+ * @param ioCase What case sensitivity to use comparing file names,
null means system sensitive.
*/
protected FileAlterationObserver(final FileEntry rootEntry, final
FileFilter fileFilter, final IOCase ioCase) {
this(rootEntry, fileFilter, toComparator(ioCase));
@@ -212,7 +293,9 @@ public class FileAlterationObserver implements Serializable
{
* Constructs an observer for the specified directory.
*
* @param directoryName the name of the directory to observe.
+ * @deprecated Use {@link #builder()}.
*/
+ @Deprecated
public FileAlterationObserver(final String directoryName) {
this(new File(directoryName));
}
@@ -222,7 +305,9 @@ public class FileAlterationObserver implements Serializable
{
*
* @param directoryName the name of the directory to observe.
* @param fileFilter The file filter or null if none.
+ * @deprecated Use {@link #builder()}.
*/
+ @Deprecated
public FileAlterationObserver(final String directoryName, final FileFilter
fileFilter) {
this(new File(directoryName), fileFilter);
}
@@ -233,7 +318,9 @@ public class FileAlterationObserver implements Serializable
{
* @param directoryName the name of the directory to observe.
* @param fileFilter The file filter or null if none.
* @param ioCase what case sensitivity to use comparing file names,
null means system sensitive.
+ * @deprecated Use {@link #builder()}.
*/
+ @Deprecated
public FileAlterationObserver(final String directoryName, final FileFilter
fileFilter, final IOCase ioCase) {
this(new File(directoryName), fileFilter, ioCase);
}
@@ -376,6 +463,10 @@ public class FileAlterationObserver implements
Serializable {
});
}
+ Comparator<File> getComparator() {
+ return comparator;
+ }
+
/**
* Returns the directory being observed.
*
diff --git
a/src/test/java/org/apache/commons/io/monitor/AbstractMonitorTest.java
b/src/test/java/org/apache/commons/io/monitor/AbstractMonitorTest.java
index 6f076d096..d807179fe 100644
--- a/src/test/java/org/apache/commons/io/monitor/AbstractMonitorTest.java
+++ b/src/test/java/org/apache/commons/io/monitor/AbstractMonitorTest.java
@@ -98,7 +98,7 @@ public abstract class AbstractMonitorTest {
* @param fileFilter The file filter to apply
*/
protected void createObserver(final File file, final FileFilter
fileFilter) {
- observer = new FileAlterationObserver(file, fileFilter);
+ observer =
FileAlterationObserver.builder().setFile(file).setFileFilter(fileFilter).getUnchecked();
observer.addListener(listener);
observer.addListener(new FileAlterationListenerAdaptor());
try {
diff --git
a/src/test/java/org/apache/commons/io/monitor/FileAlterationObserverTest.java
b/src/test/java/org/apache/commons/io/monitor/FileAlterationObserverTest.java
index b51ffcd1e..29db41d54 100644
---
a/src/test/java/org/apache/commons/io/monitor/FileAlterationObserverTest.java
+++
b/src/test/java/org/apache/commons/io/monitor/FileAlterationObserverTest.java
@@ -26,8 +26,12 @@ import java.io.IOException;
import java.util.Iterator;
import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.FilenameUtils;
+import org.apache.commons.io.IOCase;
+import org.apache.commons.io.comparator.NameFileComparator;
import org.apache.commons.io.filefilter.CanReadFileFilter;
import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.apache.commons.io.monitor.FileAlterationObserver.Builder;
import org.junit.jupiter.api.Test;
/**
@@ -35,6 +39,8 @@ import org.junit.jupiter.api.Test;
*/
public class FileAlterationObserverTest extends AbstractMonitorTest {
+ private static final String PATH_STRING_FIXTURE = "/foo";
+
/**
* Constructs a new instance.
*/
@@ -49,12 +55,16 @@ public class FileAlterationObserverTest extends
AbstractMonitorTest {
observer.checkAndNotify();
}
+ private String directoryToUnixString(final FileAlterationObserver
observer) {
+ return
FilenameUtils.separatorsToUnix(observer.getDirectory().toString());
+ }
+
/**
* Test add/remove listeners.
*/
@Test
public void testAddRemoveListeners() {
- final FileAlterationObserver observer = new
FileAlterationObserver("/foo");
+ final FileAlterationObserver observer =
FileAlterationObserver.builder().setFile(PATH_STRING_FIXTURE).getUnchecked();
// Null Listener
observer.addListener(null);
assertFalse(observer.getListeners().iterator().hasNext(),
"Listeners[1]");
@@ -74,10 +84,134 @@ public class FileAlterationObserverTest extends
AbstractMonitorTest {
assertFalse(observer.getListeners().iterator().hasNext(),
"Listeners[5]");
}
+ @Test
+ public void testBuilder_File() {
+ final File file = new File(PATH_STRING_FIXTURE);
+ final FileAlterationObserver observer =
FileAlterationObserver.builder().setFile(file).getUnchecked();
+ assertEquals(file, observer.getDirectory());
+ }
+
+ @Test
+ public void testBuilder_File_FileFilter() {
+ final File file = new File(PATH_STRING_FIXTURE);
+ // @formatter:off
+ final FileAlterationObserver observer =
FileAlterationObserver.builder()
+ .setFile(file)
+ .setFileFilter(CanReadFileFilter.CAN_READ)
+ .getUnchecked();
+ // @formatter:on
+ assertEquals(file, observer.getDirectory());
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ }
+
+ @Test
+ public void testBuilder_File_FileFilter_IOCase() {
+ final File file = new File(PATH_STRING_FIXTURE);
+ // @formatter:off
+ final FileAlterationObserver observer =
FileAlterationObserver.builder()
+ .setFile(file)
+ .setFileFilter(CanReadFileFilter.CAN_READ)
+ .setIOCase(IOCase.INSENSITIVE)
+ .getUnchecked();
+ // @formatter:on
+ assertEquals(file, observer.getDirectory());
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ assertEquals(NameFileComparator.NAME_INSENSITIVE_COMPARATOR,
observer.getComparator());
+ }
+
+ @Test
+ public void testBuilder_String() {
+ final String file = PATH_STRING_FIXTURE;
+ final FileAlterationObserver observer =
FileAlterationObserver.builder().setFile(file).getUnchecked();
+ assertEquals(file, directoryToUnixString(observer));
+ }
+
+ @Test
+ public void testBuilder_String_FileFilter() {
+ final String file = PATH_STRING_FIXTURE;
+ // @formatter:off
+ final FileAlterationObserver observer =
FileAlterationObserver.builder()
+ .setFile(file)
+ .setFileFilter(CanReadFileFilter.CAN_READ)
+ .getUnchecked();
+ // @formatter:on
+ assertEquals(file, directoryToUnixString(observer));
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ }
+
+ @Test
+ public void testBuilder_String_FileFilter_IOCase() {
+ final String file = PATH_STRING_FIXTURE;
+ // @formatter:off
+ final FileAlterationObserver observer =
FileAlterationObserver.builder()
+ .setFile(file)
+ .setFileFilter(CanReadFileFilter.CAN_READ)
+ .setIOCase(IOCase.INSENSITIVE)
+ .getUnchecked();
+ // @formatter:on
+ assertEquals(file, directoryToUnixString(observer));
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ assertEquals(NameFileComparator.NAME_INSENSITIVE_COMPARATOR,
observer.getComparator());
+ }
+
+ @Test
+ public void testConstructor_File() {
+ final File file = new File(PATH_STRING_FIXTURE);
+ @SuppressWarnings("deprecation")
+ final FileAlterationObserver observer = new
FileAlterationObserver(file);
+ assertEquals(file, observer.getDirectory());
+ }
+
+ @Test
+ public void testConstructor_File_FileFilter() {
+ final File file = new File(PATH_STRING_FIXTURE);
+ @SuppressWarnings("deprecation")
+ final FileAlterationObserver observer = new
FileAlterationObserver(file, CanReadFileFilter.CAN_READ);
+ assertEquals(file, observer.getDirectory());
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ }
+
+ @Test
+ public void testConstructor_File_FileFilter_IOCase() {
+ final File file = new File(PATH_STRING_FIXTURE);
+ @SuppressWarnings("deprecation")
+ final FileAlterationObserver observer = new
FileAlterationObserver(file, CanReadFileFilter.CAN_READ, IOCase.INSENSITIVE);
+ assertEquals(file, observer.getDirectory());
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ assertEquals(NameFileComparator.NAME_INSENSITIVE_COMPARATOR,
observer.getComparator());
+ }
+
+ @Test
+ public void testConstructor_String() {
+ final String file = PATH_STRING_FIXTURE;
+ @SuppressWarnings("deprecation")
+ final FileAlterationObserver observer = new
FileAlterationObserver(file);
+ assertEquals(file, directoryToUnixString(observer));
+ }
+
+ @Test
+ public void testConstructor_String_FileFilter() {
+ final String file = PATH_STRING_FIXTURE;
+ @SuppressWarnings("deprecation")
+ final FileAlterationObserver observer = new
FileAlterationObserver(file, CanReadFileFilter.CAN_READ);
+ assertEquals(file, directoryToUnixString(observer));
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ }
+
+ @Test
+ public void testConstructor_String_FileFilter_IOCase() {
+ final String file = PATH_STRING_FIXTURE;
+ @SuppressWarnings("deprecation")
+ final FileAlterationObserver observer = new
FileAlterationObserver(file, CanReadFileFilter.CAN_READ, IOCase.INSENSITIVE);
+ assertEquals(file, directoryToUnixString(observer));
+ assertEquals(CanReadFileFilter.CAN_READ, observer.getFileFilter());
+ assertEquals(NameFileComparator.NAME_INSENSITIVE_COMPARATOR,
observer.getComparator());
+ }
+
/**
- * Test checkAndNotify() method
+ * Tests checkAndNotify() method
*
- * @throws Exception
+ * @throws Exception Thrown on test failure.
*/
@Test
public void testDirectory() throws Exception {
@@ -373,14 +507,12 @@ public class FileAlterationObserverTest extends
AbstractMonitorTest {
*/
@Test
public void testToString() {
- final File file = new File("/foo");
-
- FileAlterationObserver observer = new FileAlterationObserver(file);
+ final File file = new File(PATH_STRING_FIXTURE);
+ final Builder builder = FileAlterationObserver.builder();
+ FileAlterationObserver observer = builder.setFile(file).getUnchecked();
assertEquals("FileAlterationObserver[file='" + file.getPath() + "',
true, listeners=0]", observer.toString());
-
- observer = new FileAlterationObserver(file,
CanReadFileFilter.CAN_READ);
+ observer =
builder.setFileFilter(CanReadFileFilter.CAN_READ).getUnchecked();
assertEquals("FileAlterationObserver[file='" + file.getPath() + "',
CanReadFileFilter, listeners=0]", observer.toString());
-
assertEquals(file, observer.getDirectory());
}
}