1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33 package com.generationjava.io.find;
34
35 import java.util.Collection;
36 import java.io.File;
37 import java.io.FileFilter;
38 import java.util.Map;
39 import java.util.List;
40 import java.util.LinkedList;
41 import java.util.Iterator;
42 import java.util.regex.Pattern;
43 import java.util.regex.Matcher;
44
45 import com.generationjava.util.WildcardUtils;
46
47 /***
48 * This is where most of the find functionality occurs. Nearly every option
49 * to find is mapped to a FileFilter, which are then chained together inside
50 * this class.
51 */
52 public class FindingFilter implements FileFilter {
53
54 private Map options;
55 private List filters = new LinkedList();
56 private boolean daystart;
57
58 public FindingFilter(Map options) {
59 this.options = options;
60 Collection entries = options.entrySet();
61 Iterator itr = entries.iterator();
62 while(itr.hasNext()) {
63 Map.Entry entry = (Map.Entry)itr.next();
64 if( entry.getKey().equals(Finder.DAYSTART) ) {
65 this.daystart = true;
66 continue;
67 }
68
69 filters.add( createFilter(entry.getKey().toString(), entry.getValue()) );
70 }
71 }
72
73 private FileFilter createFilter(String option, Object argument) {
74
75 boolean invert = false;
76 if( option.startsWith(Finder.NOT) ) {
77 invert = true;
78
79 option = option.substring(Finder.NOT.length());
80 }
81 if( option.equals(Finder.MIN) ) {
82 return new MinFilter(option, argument, invert, this);
83 }
84 if( option.equals(Finder.NEWER) ) {
85 return new NewerFilter(option, argument, invert);
86 }
87 if( option.equals(Finder.TIME) ) {
88 return new TimeFilter(option, argument, invert, this);
89 }
90 if( option.equals(Finder.EMPTY) ) {
91 return new EmptyFilter(option, argument, invert);
92 }
93 if( option.equals(Finder.SIZE) ) {
94 return new SizeFilter(option, argument, invert);
95 }
96 if( option.equals(Finder.NAME) ) {
97 return new NameFilter(option, argument, invert, false);
98 }
99 if( option.equals(Finder.INAME) ) {
100 return new NameFilter(option, argument, invert, true);
101 }
102 if( option.equals(Finder.PATH) ) {
103 return new PathFilter(option, argument, invert, false);
104 }
105 if( option.equals(Finder.IPATH) ) {
106 return new PathFilter(option, argument, invert, true);
107 }
108 if( option.equals(Finder.REGEX) ) {
109 return new RegexFilter(option, argument, invert, false);
110 }
111 if( option.equals(Finder.IREGEX) ) {
112 return new RegexFilter(option, argument, invert, true);
113 }
114 if( option.equals(Finder.TYPE) ) {
115 return new TypeFilter(option, argument, invert);
116 }
117 if( option.equals(Finder.HIDDEN) ) {
118 return new HiddenFilter(option, argument, invert);
119 }
120 if( option.equals(Finder.CAN_READ) ) {
121 return new CanReadFilter(option, argument, invert);
122 }
123 if( option.equals(Finder.CAN_WRITE) ) {
124 return new CanWriteFilter(option, argument, invert);
125 }
126 return null;
127 }
128
129 public boolean accept(File file) {
130 Iterator itr = filters.iterator();
131 while(itr.hasNext()) {
132 FileFilter filter = (FileFilter) itr.next();
133 if(filter == null) {
134 continue;
135 }
136 boolean result = filter.accept(file);
137 if(result == false) {
138 return false;
139 }
140 }
141 return true;
142 }
143
144 public boolean isDaystartConfigured() {
145 return this.daystart;
146 }
147
148
149
150
151 static boolean invert(boolean invert, boolean answer) {
152 if(invert) {
153 answer = !answer;
154 }
155 return answer;
156 }
157
158 }
159
160
161 class MinFilter implements FileFilter {
162 private Object option;
163 private boolean invert;
164 private int argument;
165 private FindingFilter parent;
166 public MinFilter(Object option, Object argument, boolean invert, FindingFilter parent) {
167 this.option = option;
168 this.invert = invert;
169 try {
170 this.argument = Integer.parseInt(argument.toString());
171 } catch(NumberFormatException nfe) {
172 throw new IllegalArgumentException("Argument "+argument+" must be an integer. ");
173 }
174 this.parent = parent;
175 }
176 public boolean accept(File file) {
177 boolean daystart = this.parent.isDaystartConfigured();
178 return FindingFilter.invert( this.invert, file.lastModified() > System.currentTimeMillis() - this.argument * 60000 );
179 }
180 }
181
182 class NewerFilter implements FileFilter {
183 private Object option;
184 private boolean invert;
185 private File argument;
186 public NewerFilter(Object option, Object argument, boolean invert) {
187 this.option = option;
188 this.invert = invert;
189 this.argument = new File(argument.toString());
190 }
191 public boolean accept(File file) {
192 return FindingFilter.invert( this.invert, file.lastModified() > this.argument.lastModified() );
193 }
194 }
195
196
197 class TimeFilter implements FileFilter {
198 private Object option;
199 private boolean invert;
200 private int argument;
201 private FindingFilter parent;
202 public TimeFilter(Object option, Object argument, boolean invert, FindingFilter parent) {
203 this.option = option;
204 this.invert = invert;
205 try {
206 this.argument = Integer.parseInt(argument.toString());
207 } catch(NumberFormatException nfe) {
208 throw new IllegalArgumentException("Argument "+argument+" must be an integer. ");
209 }
210 this.parent = parent;
211 }
212 public boolean accept(File file) {
213 boolean daystart = this.parent.isDaystartConfigured();
214 return FindingFilter.invert( this.invert, file.lastModified() > System.currentTimeMillis() - this.argument * 60000*60*24 );
215 }
216 }
217
218 class EmptyFilter implements FileFilter {
219 private Object option;
220 private boolean invert;
221 private boolean argument;
222 public EmptyFilter(Object option, Object argument, boolean invert) {
223 this.option = option;
224 this.invert = invert;
225 this.argument = new Boolean(argument.toString()).booleanValue();
226 }
227 public boolean accept(File file) {
228 return FindingFilter.invert( this.invert, (file.length() == 0) == this.argument );
229 }
230 }
231
232
233
234 class SizeFilter implements FileFilter {
235 private Object option;
236 private boolean invert;
237 private int argument;
238 public SizeFilter(Object option, Object argument, boolean invert) {
239 this.option = option;
240 this.invert = invert;
241 try {
242 this.argument = Integer.parseInt(argument.toString());
243 } catch(NumberFormatException nfe) {
244 throw new IllegalArgumentException("Argument "+argument+" must be an integer. ");
245 }
246 }
247 public boolean accept(File file) {
248 return FindingFilter.invert( this.invert, (int)(file.length()/512) == this.argument );
249 }
250 }
251
252 class NameFilter implements FileFilter {
253 private Object option;
254 private boolean invert;
255 private Object argument;
256 private boolean ignoreCase;
257 public NameFilter(Object option, Object argument, boolean invert, boolean ignoreCase) {
258 this.option = option;
259 this.invert = invert;
260 this.argument = argument;
261 this.ignoreCase = ignoreCase;
262 }
263 public boolean accept(File file) {
264 if(this.ignoreCase) {
265 return FindingFilter.invert( this.invert, WildcardUtils.match(file.getName().toLowerCase(), this.argument.toString().toLowerCase()) );
266 } else {
267 return FindingFilter.invert( this.invert, WildcardUtils.match(file.getName(), this.argument.toString()) );
268 }
269 }
270 }
271
272 class PathFilter implements FileFilter {
273 private Object option;
274 private boolean invert;
275 private Object argument;
276 private boolean ignoreCase;
277 public PathFilter(Object option, Object argument, boolean invert, boolean ignoreCase) {
278 this.option = option;
279 this.invert = invert;
280 this.argument = argument;
281 this.ignoreCase = ignoreCase;
282 }
283 public boolean accept(File file) {
284 if(this.ignoreCase) {
285 return FindingFilter.invert( this.invert, WildcardUtils.match(file.getPath().toLowerCase(), this.argument.toString().toLowerCase()) );
286 } else {
287 return FindingFilter.invert( this.invert, WildcardUtils.match(file.getPath(), this.argument.toString()) );
288 }
289 }
290 }
291
292 class RegexFilter implements FileFilter {
293 private Object option;
294 private boolean invert;
295 private Object argument;
296 private boolean ignoreCase;
297 public RegexFilter(Object option, Object argument, boolean invert, boolean ignoreCase) {
298 this.option = option;
299 this.invert = invert;
300 this.argument = argument;
301 this.ignoreCase = ignoreCase;
302 }
303 public boolean accept(File file) {
304 if(this.ignoreCase) {
305 Pattern pattern = Pattern.compile(this.argument.toString(), Pattern.CASE_INSENSITIVE);
306 Matcher matcher = pattern.matcher(file.getPath());
307 return FindingFilter.invert( this.invert, matcher.matches() );
308 } else {
309 return FindingFilter.invert( this.invert, file.getPath().matches(this.argument.toString()) );
310 }
311 }
312 }
313
314 class TypeFilter implements FileFilter {
315 private Object option;
316 private boolean invert;
317 private Object argument;
318 public TypeFilter(Object option, Object argument, boolean invert) {
319 this.option = option;
320 this.invert = invert;
321 if(!"d".equals(argument) && !"f".equals(argument)) {
322 throw new IllegalArgumentException("Type option must be 'f' or 'd'. ");
323 }
324 this.argument = argument;
325 }
326 public boolean accept(File file) {
327 if("d".equals(argument)) {
328 return FindingFilter.invert( this.invert, file.isDirectory() );
329 } else
330 if("f".equals(argument)) {
331 return FindingFilter.invert( this.invert, !file.isDirectory() );
332 } else {
333 throw new IllegalArgumentException("Type option must be 'f' or 'd'. ");
334 }
335 }
336 }
337
338 class HiddenFilter implements FileFilter {
339 private Object option;
340 private boolean invert;
341 private boolean argument;
342 public HiddenFilter(Object option, Object argument, boolean invert) {
343 this.option = option;
344 this.invert = invert;
345 this.argument = new Boolean(argument.toString()).booleanValue();
346 }
347 public boolean accept(File file) {
348 return FindingFilter.invert( this.invert, file.isHidden() == this.argument );
349 }
350 }
351
352 class CanReadFilter implements FileFilter {
353 private Object option;
354 private boolean invert;
355 private boolean argument;
356 public CanReadFilter(Object option, Object argument, boolean invert) {
357 this.option = option;
358 this.invert = invert;
359 this.argument = new Boolean(argument.toString()).booleanValue();
360 }
361 public boolean accept(File file) {
362 return FindingFilter.invert( this.invert, file.canRead() == this.argument );
363 }
364 }
365
366 class CanWriteFilter implements FileFilter {
367 private Object option;
368 private boolean invert;
369 private boolean argument;
370 public CanWriteFilter(Object option, Object argument, boolean invert) {
371 this.option = option;
372 this.invert = invert;
373 this.argument = new Boolean(argument.toString()).booleanValue();
374 }
375 public boolean accept(File file) {
376 return FindingFilter.invert( this.invert, file.canWrite() == this.argument );
377 }
378 }
379