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.vfs2.filter;
18
19 import java.io.Serializable;
20 import java.util.Date;
21 import java.util.Objects;
22
23 import org.apache.commons.vfs2.FileContent;
24 import org.apache.commons.vfs2.FileFilter;
25 import org.apache.commons.vfs2.FileObject;
26 import org.apache.commons.vfs2.FileSelectInfo;
27 import org.apache.commons.vfs2.FileSystemException;
28
29 /**
30 * Filters files based on a cutoff time, can filter either newer files or files
31 * equal to or older.
32 * <p>
33 * For example, to print all files and directories in the current directory
34 * older than one day:
35 * </p>
36 *
37 * <pre>
38 * FileSystemManager fsManager = VFS.getManager();
39 * FileObject dir = fsManager.toFileObject(new File("."));
40 * // We are interested in files older than one day
41 * long cutoff = System.currentTimeMillis() - (24 * 60 * 60 * 1000);
42 * AgeFileFilter filter = new AgeFileFilter(cutoff);
43 * FileObject[] files = dir.findFiles(new FileFilterSelector(filter));
44 * for (int i = 0; i < files.length; i++) {
45 * System.out.println(files[i]);
46 * }
47 * </pre>
48 *
49 * @author This code was originally ported from Apache Commons IO File Filter
50 * @see "https://commons.apache.org/proper/commons-io/"
51 * @since 2.4
52 */
53 public class AgeFileFilter implements FileFilter, Serializable {
54
55 private static final long serialVersionUID = 1L;
56
57 /**
58 * Tests if the specified {@code File} is newer than the specified time
59 * reference.
60 *
61 * @param fileObject the {@code File} of which the modification date must
62 * be compared, must not be {@code null}
63 * @param timeMillis the time reference measured in milliseconds since the epoch
64 * (00:00:00 GMT, January 1, 1970)
65 * @return true if the {@code File} exists and has been modified after the
66 * given time reference.
67 * @throws FileSystemException Thrown for file system errors.
68 * @throws IllegalArgumentException if the file is {@code null}
69 */
70 private static boolean isFileNewer(final FileObject fileObject, final long timeMillis) throws FileSystemException {
71 Objects.requireNonNull(fileObject, "fileObject");
72 if (!fileObject.exists()) {
73 return false;
74 }
75 try (FileContent content = fileObject.getContent()) {
76 return content.getLastModifiedTime() > timeMillis;
77 }
78 }
79
80 /** Whether the files accepted will be older or newer. */
81 private final boolean acceptOlder;
82
83 /** The cutoff time threshold. */
84 private final long cutoff;
85
86 /**
87 * Constructs a new age file filter for files older than (at or before) a
88 * certain cutoff date.
89 *
90 * @param cutoffDate the threshold age of the files
91 */
92 public AgeFileFilter(final Date cutoffDate) {
93 this(cutoffDate, true);
94 }
95
96 /**
97 * Constructs a new age file filter for files on any one side of a certain
98 * cutoff date.
99 *
100 * @param cutoffDate the threshold age of the files
101 * @param acceptOlder if true, older files (at or before the cutoff) are
102 * accepted, else newer ones (after the cutoff).
103 */
104 public AgeFileFilter(final Date cutoffDate, final boolean acceptOlder) {
105 this(cutoffDate.getTime(), acceptOlder);
106 }
107
108 /**
109 * Constructs a new age file filter for files older than (at or before) a
110 * certain File (whose last modification time will be used as reference).
111 *
112 * @param cutoffReference the file whose last modification time is used as the
113 * threshold age of the files
114 *
115 * @throws FileSystemException Error reading the last modification time from the
116 * reference file object.
117 */
118 public AgeFileFilter(final FileObject cutoffReference) throws FileSystemException {
119 this(cutoffReference, true);
120 }
121
122 /**
123 * Constructs a new age file filter for files on any one side of a certain File
124 * (whose last modification time will be used as reference).
125 *
126 * @param cutoffReference the file whose last modification time is used as the
127 * threshold age of the files
128 * @param acceptOlder if true, older files (at or before the cutoff) are
129 * accepted, else newer ones (after the cutoff).
130 *
131 * @throws FileSystemException Error reading the last modification time from the
132 * reference file object.
133 */
134 public AgeFileFilter(final FileObject cutoffReference, final boolean acceptOlder) throws FileSystemException {
135 this(cutoffReference.getContent().getLastModifiedTime(), acceptOlder);
136 }
137
138 /**
139 * Constructs a new age file filter for files equal to or older than a certain
140 * cutoff.
141 *
142 * @param cutoff the threshold age of the files
143 */
144 public AgeFileFilter(final long cutoff) {
145 this(cutoff, true);
146 }
147
148 /**
149 * Constructs a new age file filter for files on any one side of a certain
150 * cutoff.
151 *
152 * @param cutoff the threshold age of the files
153 * @param acceptOlder if true, older files (at or before the cutoff) are
154 * accepted, else newer ones (after the cutoff).
155 */
156 public AgeFileFilter(final long cutoff, final boolean acceptOlder) {
157 this.acceptOlder = acceptOlder;
158 this.cutoff = cutoff;
159 }
160
161 /**
162 * Checks to see if the last modification of the file matches cutoff favorably.
163 * <p>
164 * If last modification time equals cutoff and newer files are required, file
165 * <strong>IS NOT</strong> selected. If last modification time equals cutoff and older
166 * files are required, file <strong>IS</strong> selected.
167 * </p>
168 *
169 * @param fileInfo the File to check
170 * @return true if the file name matches
171 * @throws FileSystemException Thrown for file system errors.
172 */
173 @Override
174 public boolean accept(final FileSelectInfo fileInfo) throws FileSystemException {
175 return acceptOlder != isFileNewer(fileInfo.getFile(), cutoff);
176 }
177
178 /**
179 * Provide a String representation of this file filter.
180 *
181 * @return a String representation
182 */
183 @Override
184 public String toString() {
185 final String condition = acceptOlder ? "<=" : ">";
186 return super.toString() + "(" + condition + cutoff + ")";
187 }
188 }