Browse Source

Optimize DirectoryScanner to take advantage of include patterns which are

not beginning with wildcards
PR: 20103


git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@274819 13f79535-47bb-0310-9956-ffa450edef68
master
Antoine Levy-Lambert 22 years ago
parent
commit
787728897a
3 changed files with 158 additions and 45 deletions
  1. +3
    -0
      WHATSNEW
  2. +105
    -34
      src/main/org/apache/tools/ant/DirectoryScanner.java
  3. +50
    -11
      src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java

+ 3
- 0
WHATSNEW View File

@@ -486,6 +486,9 @@ Other changes:


* OpenVMS is detected as a valid OS family. * 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 Changes from Ant 1.5.2 to Ant 1.5.3
=================================== ===================================




+ 105
- 34
src/main/org/apache/tools/ant/DirectoryScanner.java View File

@@ -57,6 +57,9 @@ package org.apache.tools.ant;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.Vector; 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.Resource;
import org.apache.tools.ant.types.ResourceFactory; import org.apache.tools.ant.types.ResourceFactory;
import org.apache.tools.ant.types.selectors.FileSelector; import org.apache.tools.ant.types.selectors.FileSelector;
@@ -639,9 +642,59 @@ public class DirectoryScanner
} else { } else {
dirsNotIncluded.addElement(""); 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; icounter<includes.length; icounter++) {
String newpattern=SelectorUtils.rtrimWildcardTokens(includes[icounter]);
// check whether the candidate new pattern has a parent
boolean hasParent=false;
Enumeration myenum = newroots.keys();
while (myenum.hasMoreElements()) {
String existingpattern=(String)myenum.nextElement();
if (existingpattern.length() <= newpattern.length()) {
if (newpattern.indexOf(existingpattern)==0) {
hasParent=true;
}
}
}
if ( !hasParent) {
newroots.put(newpattern,includes[icounter]);
}
}
Enumeration enum2 = newroots.keys();
while (enum2.hasMoreElements()) {
String currentelement = (String) enum2.nextElement();
File myfile=new File(basedir,currentelement);
if (myfile.exists()) {
if (myfile.isDirectory()) {
if (isIncluded(currentelement) && currentelement.length()>0) {
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 * Top level invocation for a slow scan. A slow scan builds up a full
* list of excluded/included files/directories, whereas a fast scan * list of excluded/included files/directories, whereas a fast scan
@@ -745,27 +798,7 @@ public class DirectoryScanner
File file = new File(dir, newfiles[i]); File file = new File(dir, newfiles[i]);
if (file.isDirectory()) { if (file.isDirectory()) {
if (isIncluded(name)) { 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 { } else {
everythingIncluded = false; everythingIncluded = false;
dirsNotIncluded.addElement(name); dirsNotIncluded.addElement(name);
@@ -778,17 +811,7 @@ public class DirectoryScanner
} }
} else if (file.isFile()) { } else if (file.isFile()) {
if (isIncluded(name)) { 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 { } else {
everythingIncluded = false; everythingIncluded = false;
filesNotIncluded.addElement(name); 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 * Tests whether or not a name matches against at least one include
* pattern. * pattern.


+ 50
- 11
src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java View File

@@ -526,16 +526,29 @@ public final class SelectorUtils {
* *
* @param path Path to tokenize. Must not be <code>null</code>. * @param path Path to tokenize. Must not be <code>null</code>.
* *
* @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 <code>null</code>.
* @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. * Same as {@link #tokenizePath tokenizePath} but hopefully faster.
@@ -649,6 +662,32 @@ public final class SelectorUtils {
} }
return result.toString(); 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();
}
} }



Loading…
Cancel
Save