diff --git a/WHATSNEW b/WHATSNEW index 21869a87c..1b17250aa 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -486,6 +486,9 @@ Other changes: * OpenVMS is detected as a valid OS family. +* DirectoryScanner has been optimized for cases where include patterns do not start with wildcards + Bugzilla Report 20103. + Changes from Ant 1.5.2 to Ant 1.5.3 =================================== diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index f374a31bd..849a92390 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -57,6 +57,9 @@ package org.apache.tools.ant; import java.io.File; import java.io.IOException; import java.util.Vector; +import java.util.Hashtable; +import java.util.Enumeration; + import org.apache.tools.ant.types.Resource; import org.apache.tools.ant.types.ResourceFactory; import org.apache.tools.ant.types.selectors.FileSelector; @@ -639,9 +642,59 @@ public class DirectoryScanner } else { dirsNotIncluded.addElement(""); } - scandir(basedir, "", true); + checkIncludePatterns(); + } + /** + * this routine is actually checking all the include patterns + * in order to avoid scanning everything under base dir + * @since ant1.6 + */ + private void checkIncludePatterns() { + Hashtable newroots = new Hashtable(); + // put in the newroots vector the include patterns without wildcard tokens + for (int icounter=0; icounter0) { + accountForIncludedDir(currentelement,myfile,true); + } else { + if (currentelement.length() > 0) { + if (currentelement.charAt(currentelement.length()-1) != File.separatorChar) { + currentelement = currentelement + File.separatorChar; + } + } + scandir(myfile, currentelement, true); + } + } + else { + String originalpattern=(String)newroots.get(currentelement); + if (originalpattern.equals(currentelement)) { + accountForIncludedFile(currentelement,myfile); + } + } + } + } } - /** * Top level invocation for a slow scan. A slow scan builds up a full * list of excluded/included files/directories, whereas a fast scan @@ -745,27 +798,7 @@ public class DirectoryScanner File file = new File(dir, newfiles[i]); if (file.isDirectory()) { if (isIncluded(name)) { - if (!isExcluded(name)) { - if (isSelected(name, file)) { - dirsIncluded.addElement(name); - if (fast) { - scandir(file, name + File.separator, fast); - } - } else { - everythingIncluded = false; - dirsDeselected.addElement(name); - if (fast && couldHoldIncluded(name)) { - scandir(file, name + File.separator, fast); - } - } - - } else { - everythingIncluded = false; - dirsExcluded.addElement(name); - if (fast && couldHoldIncluded(name)) { - scandir(file, name + File.separator, fast); - } - } + accountForIncludedDir(name, file, fast); } else { everythingIncluded = false; dirsNotIncluded.addElement(name); @@ -778,17 +811,7 @@ public class DirectoryScanner } } else if (file.isFile()) { if (isIncluded(name)) { - if (!isExcluded(name)) { - if (isSelected(name, file)) { - filesIncluded.addElement(name); - } else { - everythingIncluded = false; - filesDeselected.addElement(name); - } - } else { - everythingIncluded = false; - filesExcluded.addElement(name); - } + accountForIncludedFile(name, file); } else { everythingIncluded = false; filesNotIncluded.addElement(name); @@ -796,7 +819,55 @@ public class DirectoryScanner } } } + /** + * process included file + * @param name path of the file relative to the directory of the fileset + * @param file included file + */ + private void accountForIncludedFile(String name, File file) { + if (!isExcluded(name)) { + if (isSelected(name, file)) { + filesIncluded.addElement(name); + } else { + everythingIncluded = false; + filesDeselected.addElement(name); + } + } else { + everythingIncluded = false; + filesExcluded.addElement(name); + } + + } + /** + * + * @param name path of the directory relative to the directory of the fileset + * @param file directory as file + * @param fast + */ + private void accountForIncludedDir(String name, File file, boolean fast) { + if (!isExcluded(name)) { + if (isSelected(name, file)) { + dirsIncluded.addElement(name); + if (fast) { + scandir(file, name + File.separator, fast); + } + } else { + everythingIncluded = false; + dirsDeselected.addElement(name); + if (fast && couldHoldIncluded(name)) { + scandir(file, name + File.separator, fast); + } + } + + } else { + everythingIncluded = false; + dirsExcluded.addElement(name); + if (fast && couldHoldIncluded(name)) { + scandir(file, name + File.separator, fast); + } + } + } /** * Tests whether or not a name matches against at least one include * pattern. diff --git a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java index 62009dbef..0ee81243d 100644 --- a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java +++ b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java @@ -526,16 +526,29 @@ public final class SelectorUtils { * * @param path Path to tokenize. Must not be null. * - * @return a Vector of path elements from the tokenized path - */ - public static Vector tokenizePath(String path) { - Vector ret = new Vector(); - StringTokenizer st = new StringTokenizer(path, File.separator); - while (st.hasMoreTokens()) { - ret.addElement(st.nextToken()); - } - return ret; - } + * @return a Vector of path elements from the tokenized path + */ + public static Vector tokenizePath (String path) { + return tokenizePath(path, File.separator); + } + /** + * Breaks a path up into a Vector of path elements, tokenizing on + * + * @param path Path to tokenize. Must not be null. + * @param separator the separator against which to tokenize. + * + * @return a Vector of path elements from the tokenized path + * @since ant 1.6 + */ + public static Vector tokenizePath (String path, String separator) { + Vector ret = new Vector(); + StringTokenizer st = new StringTokenizer(path,separator); + while (st.hasMoreTokens()) { + ret.addElement(st.nextToken()); + } + return ret; + + } /** * Same as {@link #tokenizePath tokenizePath} but hopefully faster. @@ -649,6 +662,32 @@ public final class SelectorUtils { } return result.toString(); } - + /** + * Tests if a string contains stars or question marks + * @param input a String which one wants to test for containing wildcard + * @return true if the string contains at least a star or a question mark + */ + public static boolean hasWildcards(String input) { + return (input.indexOf('*')!=-1 || input.indexOf('?')!=-1); + } + /** + * removes from a pattern all tokens to the right containing wildcards + * @param input + * @return the leftmost part of the pattern without wildcards + */ + public static String rtrimWildcardTokens(String input) { + Vector v = tokenizePath(input, File.separator); + StringBuffer sb = new StringBuffer(); + for (int counter=0; counter < v.size() ; counter++) { + if ( hasWildcards((String)v.elementAt(counter))) { + break; + } + if (counter >0) { + sb.append(File.separator); + } + sb.append((String)v.elementAt(counter)); + } + return sb.toString(); + } }