From dd6d777fec28c68e88af5345564f70a1f515cc1c Mon Sep 17 00:00:00 2001 From: Matthew Jason Benson Date: Thu, 22 Dec 2005 20:57:47 +0000 Subject: [PATCH] fixed fileset deletion slowdown. Bugzilla 37297. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@358627 13f79535-47bb-0310-9956-ffa450edef68 --- .../org/apache/tools/ant/taskdefs/Delete.java | 166 ++++++++++-------- 1 file changed, 96 insertions(+), 70 deletions(-) diff --git a/src/main/org/apache/tools/ant/taskdefs/Delete.java b/src/main/org/apache/tools/ant/taskdefs/Delete.java index b37bb5f34..318d047e2 100644 --- a/src/main/org/apache/tools/ant/taskdefs/Delete.java +++ b/src/main/org/apache/tools/ant/taskdefs/Delete.java @@ -18,20 +18,23 @@ package org.apache.tools.ant.taskdefs; import java.io.File; +import java.util.Arrays; import java.util.Vector; import java.util.Iterator; +import java.util.ArrayList; +import java.util.Comparator; import org.apache.tools.ant.Project; import org.apache.tools.ant.BuildException; import org.apache.tools.ant.taskdefs.condition.Os; -import org.apache.tools.ant.types.Path; import org.apache.tools.ant.types.FileSet; import org.apache.tools.ant.types.PatternSet; import org.apache.tools.ant.types.ResourceCollection; import org.apache.tools.ant.types.resources.Sort; import org.apache.tools.ant.types.resources.Restrict; -import org.apache.tools.ant.types.resources.BCFileSet; +import org.apache.tools.ant.types.resources.Resources; import org.apache.tools.ant.types.resources.FileResource; +import org.apache.tools.ant.types.resources.FileResourceIterator; import org.apache.tools.ant.types.resources.comparators.Reverse; import org.apache.tools.ant.types.resources.comparators.FileSystem; import org.apache.tools.ant.types.resources.comparators.ResourceComparator; @@ -74,6 +77,29 @@ public class Delete extends MatchingTask { private static final ResourceComparator REVERSE_FILESYSTEM = new Reverse(new FileSystem()); private static final ResourceSelector EXISTS = new Exists(); + private static class ReverseDirs implements ResourceCollection { + static final Comparator REVERSE = new Comparator() { + public int compare(Object foo, Object bar) { + return ((Comparable) foo).compareTo(bar) * -1; + } + }; + File basedir; + String[] dirs; + ReverseDirs(File basedir, String[] dirs) { + this.basedir = basedir; + this.dirs = dirs; + Arrays.sort(this.dirs, REVERSE); + //ArrayList al = new ArrayList(Arrays.asList(dirs)); + //Collections.reverse(al); + //this.dirs = (String[]) (al.toArray(new String[dirs.length])); + } + public Iterator iterator() { + return new FileResourceIterator(basedir, dirs); + } + public boolean isFilesystemOnly() { return true; } + public int size() { return dirs.length; } + } + protected File file = null; protected File dir = null; protected Vector filesets = new Vector(); @@ -85,7 +111,7 @@ public class Delete extends MatchingTask { private boolean quiet = false; private boolean failonerror = true; private boolean deleteOnExit = false; - private Vector rcs = new Vector(); + private Resources rcs = null; /** * Set the name of a single file to be removed. @@ -177,6 +203,10 @@ public class Delete extends MatchingTask { * @param rc the filesystem-only ResourceCollection. */ public void add(ResourceCollection rc) { + if (rc == null) { + return; + } + rcs = (rcs == null) ? new Resources() : rcs; rcs.add(rc); } @@ -467,7 +497,7 @@ public class Delete extends MatchingTask { + "Use a nested fileset element instead."); } - if (file == null && dir == null && filesets.size() == 0 && rcs.size() == 0) { + if (file == null && dir == null && filesets.size() == 0 && rcs == null) { throw new BuildException("At least one of the file or dir " + "attributes, or a nested resource collection, " + "must be set."); @@ -489,14 +519,7 @@ public class Delete extends MatchingTask { log("Deleting: " + file.getAbsolutePath()); if (!delete(file)) { - String message = "Unable to delete file " - + file.getAbsolutePath(); - if (failonerror) { - throw new BuildException(message); - } else { - log(message, quiet ? Project.MSG_VERBOSE - : Project.MSG_WARN); - } + handle("Unable to delete file " + file.getAbsolutePath()); } } } else { @@ -521,50 +544,80 @@ public class Delete extends MatchingTask { } removeDir(dir); } - Path p = new Path(getProject()); - p.addAll(rcs); + Resources resourcesToDelete = new Resources(); + resourcesToDelete.setProject(getProject()); + Resources filesetDirs = new Resources(); + filesetDirs.setProject(getProject()); + for (int i = 0; i < filesets.size(); i++) { FileSet fs = (FileSet) filesets.get(i); - p.add(includeEmpty ? new BCFileSet(fs) : fs); + resourcesToDelete.add(fs); + if (includeEmpty) { + filesetDirs.add(new ReverseDirs(fs.getDir(), + fs.getDirectoryScanner().getIncludedDirectories())); + } } if (usedMatchingTask && dir != null) { //add the files from the default fileset: FileSet implicit = getImplicitFileSet(); - p.add(includeEmpty ? new BCFileSet(implicit) : implicit); + resourcesToDelete.add(implicit); + if (includeEmpty) { + filesetDirs.add(new ReverseDirs(dir, + implicit.getDirectoryScanner().getIncludedDirectories())); + } + } + resourcesToDelete.add(filesetDirs); + if (rcs != null) { + // sort first to files, then dirs + Restrict exists = new Restrict(); + exists.add(EXISTS); + exists.add(rcs); + Sort s = new Sort(); + s.add(REVERSE_FILESYSTEM); + s.add(exists); + resourcesToDelete.add(s); } - Restrict exists = new Restrict(); - exists.add(EXISTS); - exists.add(p); - // delete the files in the resource collections; sort to files, then dirs - Sort s = new Sort(); - s.add(REVERSE_FILESYSTEM); - s.add(exists); - String errorMessage = null; try { - for (Iterator iter = s.iterator(); iter.hasNext();) { - FileResource r = (FileResource) iter.next(); - if (!(r.isDirectory()) || r.getFile().list().length == 0) { - log("Deleting " + r, verbosity); - if (!delete(r.getFile())) { - errorMessage = "Unable to delete " - + (r.isDirectory() ? "directory " : "file ") + r; + if (resourcesToDelete.isFilesystemOnly()) { + for (Iterator iter = resourcesToDelete.iterator(); iter.hasNext();) { + FileResource r = (FileResource) iter.next(); + // nonexistent resources could only occur if we already + // deleted something from a fileset: + if (!r.isExists()) { + continue; + } + if (!(r.isDirectory()) || r.getFile().list().length == 0) { + log("Deleting " + r, verbosity); + if (!delete(r.getFile()) && failonerror) { + handle("Unable to delete " + + (r.isDirectory() ? "directory " : "file ") + r); + } } } + } else { + handle(getTaskName() + " handles only filesystem resources"); } } catch (Exception e) { - errorMessage = e.getMessage(); - } - if (errorMessage != null) { - if (failonerror) { - throw new BuildException(errorMessage); - } - log(errorMessage, quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); + handle(e); } } //************************************************************************ // protected and private methods //************************************************************************ + + private void handle(String msg) { + handle(new BuildException(msg)); + } + + private void handle(Exception e) { + if (failonerror) { + throw (e instanceof BuildException) + ? (BuildException) e : new BuildException(e); + } + log(e.getMessage(), quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); + } + /** * Accommodate Windows bug encountered in both Sun and IBM JDKs. * Others possible. If the delete does not work, call System.gc(), @@ -613,27 +666,13 @@ public class Delete extends MatchingTask { } else { log("Deleting " + f.getAbsolutePath(), verbosity); if (!delete(f)) { - String message = "Unable to delete file " - + f.getAbsolutePath(); - if (failonerror) { - throw new BuildException(message); - } else { - log(message, - quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); - } + handle("Unable to delete file " + f.getAbsolutePath()); } } } log("Deleting directory " + d.getAbsolutePath(), verbosity); if (!delete(d)) { - String message = "Unable to delete directory " - + dir.getAbsolutePath(); - if (failonerror) { - throw new BuildException(message); - } else { - log(message, - quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); - } + handle("Unable to delete directory " + dir.getAbsolutePath()); } } @@ -652,14 +691,7 @@ public class Delete extends MatchingTask { File f = new File(d, files[j]); log("Deleting " + f.getAbsolutePath(), verbosity); if (!delete(f)) { - String message = "Unable to delete file " - + f.getAbsolutePath(); - if (failonerror) { - throw new BuildException(message); - } else { - log(message, - quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); - } + handle("Unable to delete file " + f.getAbsolutePath()); } } } @@ -672,14 +704,8 @@ public class Delete extends MatchingTask { if (dirFiles == null || dirFiles.length == 0) { log("Deleting " + currDir.getAbsolutePath(), verbosity); if (!delete(currDir)) { - String message = "Unable to delete directory " - + currDir.getAbsolutePath(); - if (failonerror) { - throw new BuildException(message); - } else { - log(message, - quiet ? Project.MSG_VERBOSE : Project.MSG_WARN); - } + handle("Unable to delete directory " + + currDir.getAbsolutePath()); } else { dirCount++; }