Skip to content

Commit

Permalink
Add FileAlterationObserver.Builder() and deprecate most constructors
Browse files Browse the repository at this point in the history
  • Loading branch information
garydgregory committed Oct 17, 2024
1 parent 84aff3f commit d6877f4
Show file tree
Hide file tree
Showing 4 changed files with 245 additions and 21 deletions.
1 change: 1 addition & 0 deletions src/changes/changes.xml
Original file line number Diff line number Diff line change
Expand Up @@ -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>
Expand Down
113 changes: 102 additions & 11 deletions src/main/java/org/apache/commons/io/monitor/FileAlterationObserver.java
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@

import java.io.File;
import java.io.FileFilter;
import java.io.IOException;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Arrays;
Expand All @@ -29,6 +30,7 @@

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;

Expand All @@ -44,6 +46,7 @@
* <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);
Expand All @@ -53,6 +56,7 @@
* <p>
* To manually observe a directory, initialize the observer and invoked the {@link #checkAndNotify()} method as required:
* </p>
*
* <pre>
* // initialize
* observer.init();
Expand All @@ -68,6 +72,7 @@
* <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);
Expand All @@ -76,6 +81,7 @@
* ...
* 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>
Expand All @@ -86,6 +92,7 @@
* 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(
Expand All @@ -101,12 +108,12 @@
* 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>
Expand All @@ -119,8 +126,76 @@
*/
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:
Expand Down Expand Up @@ -156,38 +231,44 @@ private static Comparator<File> toComparator(final IOCase ioCase) {
* 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);
}

/**
* 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);
}

/**
* 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);
}

/**
* 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");
Expand All @@ -200,9 +281,9 @@ private FileAlterationObserver(final FileEntry rootEntry, final FileFilter fileF
/**
* 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));
Expand All @@ -212,7 +293,9 @@ protected FileAlterationObserver(final FileEntry rootEntry, final FileFilter fil
* 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));
}
Expand All @@ -222,7 +305,9 @@ public FileAlterationObserver(final String directoryName) {
*
* @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);
}
Expand All @@ -233,7 +318,9 @@ public FileAlterationObserver(final String directoryName, final FileFilter fileF
* @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);
}
Expand Down Expand Up @@ -376,6 +463,10 @@ private void fireOnDelete(final FileEntry entry) {
});
}

Comparator<File> getComparator() {
return comparator;
}

/**
* Returns the directory being observed.
*
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -98,7 +98,7 @@ protected void checkCollectionSizes(String label,
* @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 {
Expand Down
Loading

0 comments on commit d6877f4

Please sign in to comment.