View Javadoc
1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.commons.io.filefilter;
18  
19  import java.io.File;
20  import java.io.Serializable;
21  import java.nio.file.FileVisitResult;
22  import java.nio.file.Path;
23  import java.nio.file.attribute.BasicFileAttributes;
24  import java.time.Instant;
25  import java.util.Date;
26  
27  import org.apache.commons.io.FileUtils;
28  import org.apache.commons.io.file.PathUtils;
29  
30  /**
31   * Filters files based on a cutoff time, can filter either newer files or files equal to or older.
32   * <p>
33   * For example, to print all files and directories in the current directory older than one day:
34   * </p>
35   * <h2>Using Classic IO</h2>
36   * <pre>
37   * Path dir = PathUtils.current();
38   * // We are interested in files older than one day
39   * Instant cutoff = Instant.now().minus(Duration.ofDays(1));
40   * String[] files = dir.list(new AgeFileFilter(cutoff));
41   * for (String file : files) {
42   *     System.out.println(file);
43   * }
44   * </pre>
45   *
46   * <h2>Using NIO</h2>
47   * <pre>
48   * Path dir = PathUtils.current();
49   * // We are interested in files older than one day
50   * Instant cutoff = Instant.now().minus(Duration.ofDays(1));
51   * AccumulatorPathVisitor visitor = AccumulatorPathVisitor.withLongCounters(new AgeFileFilter(cutoff));
52   * //
53   * // Walk one dir
54   * Files.<b>walkFileTree</b>(dir, Collections.emptySet(), 1, visitor);
55   * System.out.println(visitor.getPathCounters());
56   * System.out.println(visitor.getFileList());
57   * //
58   * visitor.getPathCounters().reset();
59   * //
60   * // Walk dir tree
61   * Files.<b>walkFileTree</b>(dir, visitor);
62   * System.out.println(visitor.getPathCounters());
63   * System.out.println(visitor.getDirList());
64   * System.out.println(visitor.getFileList());
65   * </pre>
66   * <h2>Deprecating Serialization</h2>
67   * <p>
68   * <em>Serialization is deprecated and will be removed in 3.0.</em>
69   * </p>
70   *
71   * @see FileFilterUtils#ageFileFilter(Date)
72   * @see FileFilterUtils#ageFileFilter(File)
73   * @see FileFilterUtils#ageFileFilter(long)
74   * @see FileFilterUtils#ageFileFilter(Date, boolean)
75   * @see FileFilterUtils#ageFileFilter(File, boolean)
76   * @see FileFilterUtils#ageFileFilter(long, boolean)
77   * @since 1.2
78   */
79  public class AgeFileFilter extends AbstractFileFilter implements Serializable {
80  
81      private static final long serialVersionUID = -2132740084016138541L;
82  
83      /** Whether the files accepted will be older or newer. */
84      private final boolean acceptOlder;
85  
86      /** The cutoff time threshold measured in milliseconds since the epoch (00:00:00 GMT, January 1, 1970). */
87      private final Instant cutoffInstant;
88  
89      /**
90       * Constructs a new age file filter for files older than (at or before) a certain cutoff date.
91       *
92       * @param cutoffDate the threshold age of the files
93       */
94      public AgeFileFilter(final Date cutoffDate) {
95          this(cutoffDate, true);
96      }
97  
98      /**
99       * Constructs a new age file filter for files on any one side of a certain cutoff date.
100      *
101      * @param cutoffDate the threshold age of the files
102      * @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the
103      *        cutoff).
104      */
105     public AgeFileFilter(final Date cutoffDate, final boolean acceptOlder) {
106         this(cutoffDate.toInstant(), acceptOlder);
107     }
108 
109     /**
110      * Constructs a new age file filter for files older than (at or before) a certain File (whose last modification time
111      * will be used as reference).
112      *
113      * @param cutoffReference the file whose last modification time is used as the threshold age of the files
114      */
115     public AgeFileFilter(final File cutoffReference) {
116         this(cutoffReference, true);
117     }
118 
119     /**
120      * Constructs a new age file filter for files on any one side of a certain File (whose last modification time will
121      * be used as reference).
122      *
123      * @param cutoffReference the file whose last modification time is used as the threshold age of the files
124      * @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the
125      *        cutoff).
126      */
127     public AgeFileFilter(final File cutoffReference, final boolean acceptOlder) {
128         this(FileUtils.lastModifiedUnchecked(cutoffReference), acceptOlder);
129     }
130 
131     /**
132      * Constructs a new age file filter for files equal to or older than a certain cutoff.
133      *
134      * @param cutoffInstant The cutoff time threshold since the epoch (00:00:00 GMT, January 1, 1970).
135      * @since 2.12.0
136      */
137     public AgeFileFilter(final Instant cutoffInstant) {
138         this(cutoffInstant, true);
139     }
140 
141     /**
142      * Constructs a new age file filter for files on any one side of a certain cutoff.
143      *
144      * @param cutoffInstant The cutoff time threshold since the epoch (00:00:00 GMT, January 1, 1970).
145      * @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the cutoff).
146      * @since 2.12.0
147      */
148     public AgeFileFilter(final Instant cutoffInstant, final boolean acceptOlder) {
149         this.acceptOlder = acceptOlder;
150         this.cutoffInstant = cutoffInstant;
151     }
152 
153     /**
154      * Constructs a new age file filter for files equal to or older than a certain cutoff
155      *
156      * @param cutoffMillis The cutoff time threshold measured in milliseconds since the epoch (00:00:00 GMT, January 1,
157      *        1970).
158      */
159     public AgeFileFilter(final long cutoffMillis) {
160         this(Instant.ofEpochMilli(cutoffMillis), true);
161     }
162 
163     /**
164      * Constructs a new age file filter for files on any one side of a certain cutoff.
165      *
166      * @param cutoffMillis The cutoff time threshold measured in milliseconds since the epoch (00:00:00 GMT, January 1,
167      *        1970).
168      * @param acceptOlder if true, older files (at or before the cutoff) are accepted, else newer ones (after the
169      *        cutoff).
170      */
171     public AgeFileFilter(final long cutoffMillis, final boolean acceptOlder) {
172         this(Instant.ofEpochMilli(cutoffMillis), acceptOlder);
173     }
174 
175     /**
176      * Checks to see if the last modification of the file matches cutoff favorably.
177      * <p>
178      * If last modification time equals cutoff and newer files are required, file <b>IS NOT</b> selected. If last
179      * modification time equals cutoff and older files are required, file <b>IS</b> selected.
180      * </p>
181      *
182      * @param file the File to check
183      * @return true if the file name matches
184      */
185     @Override
186     public boolean accept(final File file) {
187         return acceptOlder != FileUtils.isFileNewer(file, cutoffInstant);
188     }
189 
190     /**
191      * Checks to see if the last modification of the file matches cutoff favorably.
192      * <p>
193      * If last modification time equals cutoff and newer files are required, file <b>IS NOT</b> selected. If last
194      * modification time equals cutoff and older files are required, file <b>IS</b> selected.
195      * </p>
196      * @param file the File to check
197      *
198      * @return true if the file name matches
199      * @since 2.9.0
200      */
201     @Override
202     public FileVisitResult accept(final Path file, final BasicFileAttributes attributes) {
203         return get(() -> toFileVisitResult(acceptOlder != PathUtils.isNewer(file, cutoffInstant)));
204     }
205 
206     /**
207      * Provide a String representation of this file filter.
208      *
209      * @return a String representation
210      */
211     @Override
212     public String toString() {
213         final String condition = acceptOlder ? "<=" : ">";
214         return super.toString() + "(" + condition + cutoffInstant + ")";
215     }
216 }