source: release-kits/lirk3/resources/gs3-release-maker/apache-ant-1.6.5/src/main/org/apache/tools/ant/taskdefs/Delete.java@ 14982

Last change on this file since 14982 was 14982, checked in by oranfry, 16 years ago

initial import of LiRK3

File size: 22.4 KB
Line 
1/*
2 * Copyright 2000-2005 The Apache Software Foundation
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 *
16 */
17
18package org.apache.tools.ant.taskdefs;
19
20import java.io.File;
21import java.util.Vector;
22import org.apache.tools.ant.BuildException;
23import org.apache.tools.ant.DirectoryScanner;
24import org.apache.tools.ant.Project;
25import org.apache.tools.ant.taskdefs.condition.Os;
26import org.apache.tools.ant.types.FileSet;
27import org.apache.tools.ant.types.PatternSet;
28import org.apache.tools.ant.types.selectors.AndSelector;
29import org.apache.tools.ant.types.selectors.ContainsRegexpSelector;
30import org.apache.tools.ant.types.selectors.ContainsSelector;
31import org.apache.tools.ant.types.selectors.DateSelector;
32import org.apache.tools.ant.types.selectors.DependSelector;
33import org.apache.tools.ant.types.selectors.DepthSelector;
34import org.apache.tools.ant.types.selectors.ExtendSelector;
35import org.apache.tools.ant.types.selectors.FilenameSelector;
36import org.apache.tools.ant.types.selectors.MajoritySelector;
37import org.apache.tools.ant.types.selectors.NoneSelector;
38import org.apache.tools.ant.types.selectors.NotSelector;
39import org.apache.tools.ant.types.selectors.OrSelector;
40import org.apache.tools.ant.types.selectors.PresentSelector;
41import org.apache.tools.ant.types.selectors.SelectSelector;
42import org.apache.tools.ant.types.selectors.SizeSelector;
43import org.apache.tools.ant.types.selectors.FileSelector;
44import org.apache.tools.ant.types.selectors.modifiedselector.ModifiedSelector;
45
46/**
47 * Deletes a file or directory, or set of files defined by a fileset.
48 * The original delete task would delete a file, or a set of files
49 * using the include/exclude syntax. The deltree task would delete a
50 * directory tree. This task combines the functionality of these two
51 * originally distinct tasks.
52 * <p>Currently Delete extends MatchingTask. This is intended <i>only</i>
53 * to provide backwards compatibility for a release. The future position
54 * is to use nested filesets exclusively.</p>
55 *
56 * @since Ant 1.2
57 *
58 * @ant.task category="filesystem"
59 */
60public class Delete extends MatchingTask {
61 private static final int DELETE_RETRY_SLEEP_MILLIS = 10;
62 protected File file = null;
63 protected File dir = null;
64 protected Vector filesets = new Vector();
65 protected boolean usedMatchingTask = false;
66 // by default, remove matching empty dirs
67 protected boolean includeEmpty = false;
68
69 private int verbosity = Project.MSG_VERBOSE;
70 private boolean quiet = false;
71 private boolean failonerror = true;
72 private boolean deleteOnExit = false;
73
74 /**
75 * Set the name of a single file to be removed.
76 *
77 * @param file the file to be deleted
78 */
79 public void setFile(File file) {
80 this.file = file;
81 }
82
83 /**
84 * Set the directory from which files are to be deleted
85 *
86 * @param dir the directory path.
87 */
88 public void setDir(File dir) {
89 this.dir = dir;
90 }
91
92 /**
93 * If true, list all names of deleted files.
94 *
95 * @param verbose "true" or "on"
96 */
97 public void setVerbose(boolean verbose) {
98 if (verbose) {
99 this.verbosity = Project.MSG_INFO;
100 } else {
101 this.verbosity = Project.MSG_VERBOSE;
102 }
103 }
104
105 /**
106 * If true and the file does not exist, do not display a diagnostic
107 * message or modify the exit status to reflect an error.
108 * This means that if a file or directory cannot be deleted,
109 * then no error is reported. This setting emulates the
110 * -f option to the Unix &quot;rm&quot; command.
111 * Default is false meaning things are &quot;noisy&quot;
112 * @param quiet "true" or "on"
113 */
114 public void setQuiet(boolean quiet) {
115 this.quiet = quiet;
116 if (quiet) {
117 this.failonerror = false;
118 }
119 }
120
121 /**
122 * If false, note errors but continue.
123 *
124 * @param failonerror true or false
125 */
126 public void setFailOnError(boolean failonerror) {
127 this.failonerror = failonerror;
128 }
129
130 /**
131 * If true, on failure to delete, note the error and set
132 * the deleteonexit flag, and continue
133 *
134 * @param deleteOnExit true or false
135 */
136 public void setDeleteOnExit(boolean deleteOnExit) {
137 this.deleteOnExit = deleteOnExit;
138 }
139
140
141 /**
142 * If true, delete empty directories.
143 * @param includeEmpty if true delete empty directories (only
144 * for filesets). Default is false.
145 */
146 public void setIncludeEmptyDirs(boolean includeEmpty) {
147 this.includeEmpty = includeEmpty;
148 }
149
150 /**
151 * Adds a set of files to be deleted.
152 * @param set the set of files to be deleted
153 */
154 public void addFileset(FileSet set) {
155 filesets.addElement(set);
156 }
157
158 /**
159 * add a name entry on the include list
160 * @return a NameEntry object to be configured
161 */
162 public PatternSet.NameEntry createInclude() {
163 usedMatchingTask = true;
164 return super.createInclude();
165 }
166
167 /**
168 * add a name entry on the include files list
169 * @return an NameEntry object to be configured
170 */
171 public PatternSet.NameEntry createIncludesFile() {
172 usedMatchingTask = true;
173 return super.createIncludesFile();
174 }
175
176 /**
177 * add a name entry on the exclude list
178 * @return an NameEntry object to be configured
179 */
180 public PatternSet.NameEntry createExclude() {
181 usedMatchingTask = true;
182 return super.createExclude();
183 }
184
185 /**
186 * add a name entry on the include files list
187 * @return an NameEntry object to be configured
188 */
189 public PatternSet.NameEntry createExcludesFile() {
190 usedMatchingTask = true;
191 return super.createExcludesFile();
192 }
193
194 /**
195 * add a set of patterns
196 * @return PatternSet object to be configured
197 */
198 public PatternSet createPatternSet() {
199 usedMatchingTask = true;
200 return super.createPatternSet();
201 }
202
203 /**
204 * Sets the set of include patterns. Patterns may be separated by a comma
205 * or a space.
206 *
207 * @param includes the string containing the include patterns
208 */
209 public void setIncludes(String includes) {
210 usedMatchingTask = true;
211 super.setIncludes(includes);
212 }
213
214 /**
215 * Sets the set of exclude patterns. Patterns may be separated by a comma
216 * or a space.
217 *
218 * @param excludes the string containing the exclude patterns
219 */
220 public void setExcludes(String excludes) {
221 usedMatchingTask = true;
222 super.setExcludes(excludes);
223 }
224
225 /**
226 * Sets whether default exclusions should be used or not.
227 *
228 * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
229 * should be used, "false"|"off"|"no" when they
230 * shouldn't be used.
231 */
232 public void setDefaultexcludes(boolean useDefaultExcludes) {
233 usedMatchingTask = true;
234 super.setDefaultexcludes(useDefaultExcludes);
235 }
236
237 /**
238 * Sets the name of the file containing the includes patterns.
239 *
240 * @param includesfile A string containing the filename to fetch
241 * the include patterns from.
242 */
243 public void setIncludesfile(File includesfile) {
244 usedMatchingTask = true;
245 super.setIncludesfile(includesfile);
246 }
247
248 /**
249 * Sets the name of the file containing the includes patterns.
250 *
251 * @param excludesfile A string containing the filename to fetch
252 * the include patterns from.
253 */
254 public void setExcludesfile(File excludesfile) {
255 usedMatchingTask = true;
256 super.setExcludesfile(excludesfile);
257 }
258
259 /**
260 * Sets case sensitivity of the file system
261 *
262 * @param isCaseSensitive "true"|"on"|"yes" if file system is case
263 * sensitive, "false"|"off"|"no" when not.
264 */
265 public void setCaseSensitive(boolean isCaseSensitive) {
266 usedMatchingTask = true;
267 super.setCaseSensitive(isCaseSensitive);
268 }
269
270 /**
271 * Sets whether or not symbolic links should be followed.
272 *
273 * @param followSymlinks whether or not symbolic links should be followed
274 */
275 public void setFollowSymlinks(boolean followSymlinks) {
276 usedMatchingTask = true;
277 super.setFollowSymlinks(followSymlinks);
278 }
279
280 /**
281 * add a "Select" selector entry on the selector list
282 * @param selector the selector to be added
283 */
284 public void addSelector(SelectSelector selector) {
285 usedMatchingTask = true;
286 super.addSelector(selector);
287 }
288
289 /**
290 * add an "And" selector entry on the selector list
291 * @param selector the selector to be added
292 */
293 public void addAnd(AndSelector selector) {
294 usedMatchingTask = true;
295 super.addAnd(selector);
296 }
297
298 /**
299 * add an "Or" selector entry on the selector list
300 * @param selector the selector to be added
301 */
302 public void addOr(OrSelector selector) {
303 usedMatchingTask = true;
304 super.addOr(selector);
305 }
306
307 /**
308 * add a "Not" selector entry on the selector list
309 * @param selector the selector to be added
310 */
311 public void addNot(NotSelector selector) {
312 usedMatchingTask = true;
313 super.addNot(selector);
314 }
315
316 /**
317 * add a "None" selector entry on the selector list
318 * @param selector the selector to be added
319 */
320 public void addNone(NoneSelector selector) {
321 usedMatchingTask = true;
322 super.addNone(selector);
323 }
324
325 /**
326 * add a majority selector entry on the selector list
327 * @param selector the selector to be added
328 */
329 public void addMajority(MajoritySelector selector) {
330 usedMatchingTask = true;
331 super.addMajority(selector);
332 }
333
334 /**
335 * add a selector date entry on the selector list
336 * @param selector the selector to be added
337 */
338 public void addDate(DateSelector selector) {
339 usedMatchingTask = true;
340 super.addDate(selector);
341 }
342
343 /**
344 * add a selector size entry on the selector list
345 * @param selector the selector to be added
346 */
347 public void addSize(SizeSelector selector) {
348 usedMatchingTask = true;
349 super.addSize(selector);
350 }
351
352 /**
353 * add a selector filename entry on the selector list
354 * @param selector the selector to be added
355 */
356 public void addFilename(FilenameSelector selector) {
357 usedMatchingTask = true;
358 super.addFilename(selector);
359 }
360
361 /**
362 * add an extended selector entry on the selector list
363 * @param selector the selector to be added
364 */
365 public void addCustom(ExtendSelector selector) {
366 usedMatchingTask = true;
367 super.addCustom(selector);
368 }
369
370 /**
371 * add a contains selector entry on the selector list
372 * @param selector the selector to be added
373 */
374 public void addContains(ContainsSelector selector) {
375 usedMatchingTask = true;
376 super.addContains(selector);
377 }
378
379 /**
380 * add a present selector entry on the selector list
381 * @param selector the selector to be added
382 */
383 public void addPresent(PresentSelector selector) {
384 usedMatchingTask = true;
385 super.addPresent(selector);
386 }
387
388 /**
389 * add a depth selector entry on the selector list
390 * @param selector the selector to be added
391 */
392 public void addDepth(DepthSelector selector) {
393 usedMatchingTask = true;
394 super.addDepth(selector);
395 }
396
397 /**
398 * add a depends selector entry on the selector list
399 * @param selector the selector to be added
400 */
401 public void addDepend(DependSelector selector) {
402 usedMatchingTask = true;
403 super.addDepend(selector);
404 }
405
406 /**
407 * add a regular expression selector entry on the selector list
408 * @param selector the selector to be added
409 */
410 public void addContainsRegexp(ContainsRegexpSelector selector) {
411 usedMatchingTask = true;
412 super.addContainsRegexp(selector);
413 }
414
415 /**
416 * add the modified selector
417 * @param selector the selector to add
418 * @since ant 1.6
419 */
420 public void addModified(ModifiedSelector selector) {
421 usedMatchingTask = true;
422 super.addModified(selector);
423 }
424
425 /**
426 * add an arbitrary selector
427 * @param selector the selector to be added
428 * @since Ant 1.6
429 */
430 public void add(FileSelector selector) {
431 usedMatchingTask = true;
432 super.add(selector);
433 }
434
435 /**
436 * Delete the file(s).
437 * @exception BuildException if an error occurs
438 */
439 public void execute() throws BuildException {
440 if (usedMatchingTask) {
441 log("DEPRECATED - Use of the implicit FileSet is deprecated. "
442 + "Use a nested fileset element instead.");
443 }
444
445 if (file == null && dir == null && filesets.size() == 0) {
446 throw new BuildException("At least one of the file or dir "
447 + "attributes, or a fileset element, "
448 + "must be set.");
449 }
450
451 if (quiet && failonerror) {
452 throw new BuildException("quiet and failonerror cannot both be "
453 + "set to true", getLocation());
454 }
455
456
457 // delete the single file
458 if (file != null) {
459 if (file.exists()) {
460 if (file.isDirectory()) {
461 log("Directory " + file.getAbsolutePath()
462 + " cannot be removed using the file attribute. "
463 + "Use dir instead.");
464 } else {
465 log("Deleting: " + file.getAbsolutePath());
466
467 if (!delete(file)) {
468 String message = "Unable to delete file "
469 + file.getAbsolutePath();
470 if (failonerror) {
471 throw new BuildException(message);
472 } else {
473 log(message, quiet ? Project.MSG_VERBOSE
474 : Project.MSG_WARN);
475 }
476 }
477 }
478 } else {
479 log("Could not find file " + file.getAbsolutePath()
480 + " to delete.",
481 Project.MSG_VERBOSE);
482 }
483 }
484
485 // delete the directory
486 if (dir != null && dir.exists() && dir.isDirectory()
487 && !usedMatchingTask) {
488 /*
489 If verbosity is MSG_VERBOSE, that mean we are doing
490 regular logging (backwards as that sounds). In that
491 case, we want to print one message about deleting the
492 top of the directory tree. Otherwise, the removeDir
493 method will handle messages for _all_ directories.
494 */
495 if (verbosity == Project.MSG_VERBOSE) {
496 log("Deleting directory " + dir.getAbsolutePath());
497 }
498 removeDir(dir);
499 }
500
501 // delete the files in the filesets
502 for (int i = 0; i < filesets.size(); i++) {
503 FileSet fs = (FileSet) filesets.elementAt(i);
504 try {
505 DirectoryScanner ds = fs.getDirectoryScanner(getProject());
506 String[] files = ds.getIncludedFiles();
507 String[] dirs = ds.getIncludedDirectories();
508 removeFiles(fs.getDir(getProject()), files, dirs);
509 } catch (BuildException be) {
510 // directory doesn't exist or is not readable
511 if (failonerror) {
512 throw be;
513 } else {
514 log(be.getMessage(),
515 quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
516 }
517 }
518 }
519
520 // delete the files from the default fileset
521 if (usedMatchingTask && dir != null) {
522 try {
523 DirectoryScanner ds = super.getDirectoryScanner(dir);
524 String[] files = ds.getIncludedFiles();
525 String[] dirs = ds.getIncludedDirectories();
526 removeFiles(dir, files, dirs);
527 } catch (BuildException be) {
528 // directory doesn't exist or is not readable
529 if (failonerror) {
530 throw be;
531 } else {
532 log(be.getMessage(),
533 quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
534 }
535 }
536 }
537 }
538
539//************************************************************************
540// protected and private methods
541//************************************************************************
542 /**
543 * Accommodate Windows bug encountered in both Sun and IBM JDKs.
544 * Others possible. If the delete does not work, call System.gc(),
545 * wait a little and try again.
546 */
547 private boolean delete(File f) {
548 if (!f.delete()) {
549 if (Os.isFamily("windows")) {
550 System.gc();
551 }
552 try {
553 Thread.sleep(DELETE_RETRY_SLEEP_MILLIS);
554 } catch (InterruptedException ex) {
555 // Ignore Exception
556 }
557 if (!f.delete()) {
558 if (deleteOnExit) {
559 int level = quiet ? Project.MSG_VERBOSE : Project.MSG_INFO;
560 log("Failed to delete " + f + ", calling deleteOnExit."
561 + " This attempts to delete the file when the ant jvm"
562 + " has exited and might not succeed."
563 , level);
564 f.deleteOnExit();
565 return true;
566 }
567 return false;
568 }
569 }
570 return true;
571 }
572
573 /**
574 * Delete a directory
575 *
576 * @param d the directory to delete
577 */
578 protected void removeDir(File d) {
579 String[] list = d.list();
580 if (list == null) {
581 list = new String[0];
582 }
583 for (int i = 0; i < list.length; i++) {
584 String s = list[i];
585 File f = new File(d, s);
586 if (f.isDirectory()) {
587 removeDir(f);
588 } else {
589 log("Deleting " + f.getAbsolutePath(), verbosity);
590 if (!delete(f)) {
591 String message = "Unable to delete file "
592 + f.getAbsolutePath();
593 if (failonerror) {
594 throw new BuildException(message);
595 } else {
596 log(message,
597 quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
598 }
599 }
600 }
601 }
602 log("Deleting directory " + d.getAbsolutePath(), verbosity);
603 if (!delete(d)) {
604 String message = "Unable to delete directory "
605 + dir.getAbsolutePath();
606 if (failonerror) {
607 throw new BuildException(message);
608 } else {
609 log(message,
610 quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
611 }
612 }
613 }
614
615 /**
616 * remove an array of files in a directory, and a list of subdirectories
617 * which will only be deleted if 'includeEmpty' is true
618 * @param d directory to work from
619 * @param files array of files to delete; can be of zero length
620 * @param dirs array of directories to delete; can of zero length
621 */
622 protected void removeFiles(File d, String[] files, String[] dirs) {
623 if (files.length > 0) {
624 log("Deleting " + files.length + " files from "
625 + d.getAbsolutePath());
626 for (int j = 0; j < files.length; j++) {
627 File f = new File(d, files[j]);
628 log("Deleting " + f.getAbsolutePath(), verbosity);
629 if (!delete(f)) {
630 String message = "Unable to delete file "
631 + f.getAbsolutePath();
632 if (failonerror) {
633 throw new BuildException(message);
634 } else {
635 log(message,
636 quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
637 }
638 }
639 }
640 }
641
642 if (dirs.length > 0 && includeEmpty) {
643 int dirCount = 0;
644 for (int j = dirs.length - 1; j >= 0; j--) {
645 File currDir = new File(d, dirs[j]);
646 String[] dirFiles = currDir.list();
647 if (dirFiles == null || dirFiles.length == 0) {
648 log("Deleting " + currDir.getAbsolutePath(), verbosity);
649 if (!delete(currDir)) {
650 String message = "Unable to delete directory "
651 + currDir.getAbsolutePath();
652 if (failonerror) {
653 throw new BuildException(message);
654 } else {
655 log(message,
656 quiet ? Project.MSG_VERBOSE : Project.MSG_WARN);
657 }
658 } else {
659 dirCount++;
660 }
661 }
662 }
663
664 if (dirCount > 0) {
665 log("Deleted " + dirCount + " director"
666 + (dirCount == 1 ? "y" : "ies")
667 + " from " + d.getAbsolutePath());
668 }
669 }
670 }
671}
Note: See TracBrowser for help on using the repository browser.