You are viewing a plain text version of this content. The canonical link for it is here.
Posted to notifications@ant.apache.org by bo...@apache.org on 2008/09/17 17:11:29 UTC
svn commit: r696336 - in /ant/core/trunk/src/main/org/apache/tools/ant:
DirectoryScanner.java types/selectors/SelectorUtils.java
types/selectors/TokenizedPath.java types/selectors/TokenizedPattern.java
Author: bodewig
Date: Wed Sep 17 08:11:28 2008
New Revision: 696336
URL: http://svn.apache.org/viewvc?rev=696336&view=rev
Log:
avoid redundant tokenization. this is almost complete except for non-wildcard include patterns, will take care of them next.
Modified:
ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java
Modified: ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java?rev=696336&r1=696335&r2=696336&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java Wed Sep 17 08:11:28 2008
@@ -860,8 +860,8 @@
throw illegal;
}
}
- if (isIncluded("")) {
- if (!isExcluded("")) {
+ if (isIncluded(TokenizedPath.EMPTY_PATH)) {
+ if (!isExcluded(TokenizedPath.EMPTY_PATH)) {
if (isSelected("", basedir)) {
dirsIncluded.addElement("");
} else {
@@ -997,19 +997,11 @@
continue;
}
if (myfile.isDirectory()) {
- if (isIncluded(currentelement)
+ if (isIncluded(currentPath)
&& currentelement.length() > 0) {
- accountForIncludedDir(currentelement, myfile, true);
+ accountForIncludedDir(currentPath, myfile, true);
} else {
- if (currentelement.length() > 0) {
- if (currentelement.charAt(currentelement
- .length() - 1)
- != File.separatorChar) {
- currentelement =
- currentelement + File.separatorChar;
- }
- }
- scandir(myfile, currentelement, true);
+ scandir(myfile, currentPath, true);
}
} else {
String originalpattern = (String) entry.getValue();
@@ -1017,7 +1009,7 @@
? originalpattern.equals(currentelement)
: originalpattern.equalsIgnoreCase(currentelement);
if (included) {
- accountForIncludedFile(currentelement, myfile);
+ accountForIncludedFile(currentPath, myfile);
}
}
}
@@ -1099,9 +1091,9 @@
private void processSlowScan(String[] arr) {
for (int i = 0; i < arr.length; i++) {
- if (!couldHoldIncluded(arr[i])) {
- scandir(new File(basedir, arr[i]),
- arr[i] + File.separator, false);
+ TokenizedPath path = new TokenizedPath(arr[i]);
+ if (!couldHoldIncluded(path)) {
+ scandir(new File(basedir, arr[i]), path, false);
}
}
}
@@ -1127,6 +1119,30 @@
* @see #slowScan
*/
protected void scandir(File dir, String vpath, boolean fast) {
+ scandir(dir, new TokenizedPath(vpath), fast);
+ }
+
+ /**
+ * Scan the given directory for files and directories. Found files and
+ * directories are placed in their respective collections, based on the
+ * matching of includes, excludes, and the selectors. When a directory
+ * is found, it is scanned recursively.
+ *
+ * @param dir The directory to scan. Must not be <code>null</code>.
+ * @param path The path relative to the base directory (needed to
+ * prevent problems with an absolute path when using
+ * dir). Must not be <code>null</code>.
+ * @param fast Whether or not this call is part of a fast scan.
+ *
+ * @see #filesIncluded
+ * @see #filesNotIncluded
+ * @see #filesExcluded
+ * @see #dirsIncluded
+ * @see #dirsNotIncluded
+ * @see #dirsExcluded
+ * @see #slowScan
+ */
+ private void scandir(File dir, TokenizedPath path, boolean fast) {
if (dir == null) {
throw new BuildException("dir must not be null.");
}
@@ -1141,11 +1157,16 @@
+ dir.getAbsolutePath() + "'");
}
}
- scandir(dir, vpath, fast, newfiles, new LinkedList());
+ scandir(dir, path, fast, newfiles, new LinkedList());
}
- private void scandir(File dir, String vpath, boolean fast,
+ private void scandir(File dir, TokenizedPath path, boolean fast,
String[] newfiles, LinkedList directoryNamesFollowed) {
+ String vpath = path.toString();
+ if (vpath.length() > 0 && !vpath.endsWith(File.separator)) {
+ vpath += File.separator;
+ }
+
// avoid double scanning of directories, can only happen in fast mode
if (fast && hasBeenScanned(vpath)) {
return;
@@ -1177,11 +1198,12 @@
for (int i = 0; i < newfiles.length; i++) {
String name = vpath + newfiles[i];
+ TokenizedPath newPath = new TokenizedPath(path, newfiles[i]);
File file = new File(dir, newfiles[i]);
String[] children = list(file);
if (children == null) { // probably file
- if (isIncluded(name)) {
- accountForIncludedFile(name, file);
+ if (isIncluded(newPath)) {
+ accountForIncludedFile(newPath, file);
} else {
everythingIncluded = false;
filesNotIncluded.addElement(name);
@@ -1199,20 +1221,19 @@
continue;
}
- if (isIncluded(name)) {
- accountForIncludedDir(name, file, fast, children,
+ if (isIncluded(newPath)) {
+ accountForIncludedDir(newPath, file, fast, children,
directoryNamesFollowed);
} else {
everythingIncluded = false;
dirsNotIncluded.addElement(name);
- if (fast && couldHoldIncluded(name)) {
- scandir(file, name + File.separator, fast, children,
+ if (fast && couldHoldIncluded(newPath)) {
+ scandir(file, newPath, fast, children,
directoryNamesFollowed);
}
}
if (!fast) {
- scandir(file, name + File.separator, fast, children,
- directoryNamesFollowed);
+ scandir(file, newPath, fast, children, directoryNamesFollowed);
}
}
}
@@ -1227,7 +1248,7 @@
* @param name path of the file relative to the directory of the FileSet.
* @param file included File.
*/
- private void accountForIncludedFile(String name, File file) {
+ private void accountForIncludedFile(TokenizedPath name, File file) {
processIncluded(name, file, filesIncluded, filesExcluded,
filesDeselected);
}
@@ -1239,32 +1260,34 @@
* @param file directory as File.
* @param fast whether to perform fast scans.
*/
- private void accountForIncludedDir(String name, File file, boolean fast) {
+ private void accountForIncludedDir(TokenizedPath name, File file,
+ boolean fast) {
processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected);
if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) {
- scandir(file, name + File.separator, fast);
+ scandir(file, name, fast);
}
}
- private void accountForIncludedDir(String name, File file, boolean fast,
+ private void accountForIncludedDir(TokenizedPath name,
+ File file, boolean fast,
String[] children,
LinkedList directoryNamesFollowed) {
processIncluded(name, file, dirsIncluded, dirsExcluded, dirsDeselected);
if (fast && couldHoldIncluded(name) && !contentsExcluded(name)) {
- scandir(file, name + File.separator, fast, children,
- directoryNamesFollowed);
+ scandir(file, name, fast, children, directoryNamesFollowed);
}
}
- private void processIncluded(String name, File file, Vector inc,
- Vector exc, Vector des) {
-
+ private void processIncluded(TokenizedPath path,
+ File file, Vector inc, Vector exc,
+ Vector des) {
+ String name = path.toString();
if (inc.contains(name) || exc.contains(name) || des.contains(name)) {
return;
}
boolean included = false;
- if (isExcluded(name)) {
+ if (isExcluded(path)) {
exc.add(name);
} else if (isSelected(name, file)) {
included = true;
@@ -1284,15 +1307,27 @@
* include pattern, or <code>false</code> otherwise.
*/
protected boolean isIncluded(String name) {
+ return isIncluded(new TokenizedPath(name));
+ }
+
+ /**
+ * Test whether or not a name matches against at least one include
+ * pattern.
+ *
+ * @param name The name to match. Must not be <code>null</code>.
+ * @return <code>true</code> when the name matches against at least one
+ * include pattern, or <code>false</code> otherwise.
+ */
+ private boolean isIncluded(TokenizedPath path) {
ensureNonPatternSetsReady();
if (isCaseSensitive()
- ? includeNonPatterns.contains(name)
- : includeNonPatterns.contains(name.toUpperCase())) {
+ ? includeNonPatterns.contains(path.toString())
+ : includeNonPatterns.contains(path.toString().toUpperCase())) {
return true;
}
for (int i = 0; i < includePatterns.length; i++) {
- if (includePatterns[i].matchPath(name, isCaseSensitive())) {
+ if (includePatterns[i].matchPath(path, isCaseSensitive())) {
return true;
}
}
@@ -1308,12 +1343,29 @@
* least one include pattern, or <code>false</code> otherwise.
*/
protected boolean couldHoldIncluded(String name) {
- final TokenizedPath tokenizedName = new TokenizedPath(name);
+ return couldHoldIncluded(new TokenizedPath(name));
+ }
+
+ /**
+ * Test whether or not a name matches the start of at least one include
+ * pattern.
+ *
+ * @param tokenizedName The name to match. Must not be <code>null</code>.
+ * @return <code>true</code> when the name matches against the start of at
+ * least one include pattern, or <code>false</code> otherwise.
+ */
+ private boolean couldHoldIncluded(TokenizedPath tokenizedName) {
+ int wildCardCount = 0;
for (int i = 0; i < includes.length; i++) {
- TokenizedPattern tokenizedInclude =
- new TokenizedPattern(includes[i]);
+ TokenizedPattern tokenizedInclude;
+ boolean wildcard = SelectorUtils.hasWildcards(includes[i]);
+ if (wildcard) {
+ tokenizedInclude = includePatterns[wildCardCount++];
+ } else {
+ tokenizedInclude = new TokenizedPattern(includes[i]);
+ }
if (tokenizedInclude.matchStartOf(tokenizedName, isCaseSensitive())
- && isMorePowerfulThanExcludes(name, includes[i])
+ && isMorePowerfulThanExcludes(tokenizedName.toString())
&& isDeeper(tokenizedInclude, tokenizedName)) {
return true;
}
@@ -1346,17 +1398,15 @@
* IMPORTANT : this function should return false "with care".
*
* @param name the relative path to test.
- * @param includepattern one include pattern.
* @return true if there is no exclude pattern more powerful than
* this include pattern.
* @since Ant 1.6
*/
- private boolean isMorePowerfulThanExcludes(String name,
- String includepattern) {
+ private boolean isMorePowerfulThanExcludes(String name) {
final String soughtexclude =
name + File.separatorChar + SelectorUtils.DEEP_TREE_MATCH;
- for (int counter = 0; counter < excludes.length; counter++) {
- if (excludes[counter].equals(soughtexclude)) {
+ for (int counter = 0; counter < excludePatterns.length; counter++) {
+ if (excludePatterns[counter].toString().equals(soughtexclude)) {
return false;
}
}
@@ -1365,16 +1415,14 @@
/**
* Test whether all contents of the specified directory must be excluded.
- * @param name the directory name to check.
+ * @param path the path to check.
* @return whether all the specified directory's contents are excluded.
*/
- private boolean contentsExcluded(String name) {
- name = (name.endsWith(File.separator)) ? name : name + File.separator;
- for (int i = 0; i < excludes.length; i++) {
- String e = excludes[i];
- if (e.endsWith(SelectorUtils.DEEP_TREE_MATCH)
- && SelectorUtils.matchPath(e.substring(0, e.length() - 2),
- name, isCaseSensitive())) {
+ private boolean contentsExcluded(TokenizedPath path) {
+ for (int i = 0; i < excludePatterns.length; i++) {
+ if (excludePatterns[i].endsWith(SelectorUtils.DEEP_TREE_MATCH)
+ && excludePatterns[i].withoutLastToken()
+ .matchPath(path, isCaseSensitive())) {
return true;
}
}
@@ -1390,11 +1438,23 @@
* exclude pattern, or <code>false</code> otherwise.
*/
protected boolean isExcluded(String name) {
+ return isExcluded(new TokenizedPath(name));
+ }
+
+ /**
+ * Test whether or not a name matches against at least one exclude
+ * pattern.
+ *
+ * @param name The name to match. Must not be <code>null</code>.
+ * @return <code>true</code> when the name matches against at least one
+ * exclude pattern, or <code>false</code> otherwise.
+ */
+ private boolean isExcluded(TokenizedPath name) {
ensureNonPatternSetsReady();
if (isCaseSensitive()
- ? excludeNonPatterns.contains(name)
- : excludeNonPatterns.contains(name.toUpperCase())) {
+ ? excludeNonPatterns.contains(name.toString())
+ : excludeNonPatterns.contains(name.toString().toUpperCase())) {
return true;
}
for (int i = 0; i < excludePatterns.length; i++) {
Modified: ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java?rev=696336&r1=696335&r2=696336&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java Wed Sep 17 08:11:28 2008
@@ -216,12 +216,21 @@
}
/**
- * Core implementation of matchPath. It is isolated so that it can be called from
- * PathPattern.
+ * Core implementation of matchPath. It is isolated so that it
+ * can be called from TokenizedPattern.
*/
- static boolean matchPath(String[] tokenizedPattern, String str, boolean isCaseSensitive) {
- String[] strDirs = tokenizePathAsArray(str);
+ static boolean matchPath(String[] tokenizedPattern, String str,
+ boolean isCaseSensitive) {
+ return matchPath(tokenizedPattern, tokenizePathAsArray(str),
+ isCaseSensitive);
+ }
+ /**
+ * Core implementation of matchPath. It is isolated so that it
+ * can be called from TokenizedPattern.
+ */
+ static boolean matchPath(String[] tokenizedPattern, String[] strDirs,
+ boolean isCaseSensitive) {
int patIdxStart = 0;
int patIdxEnd = tokenizedPattern.length - 1;
int strIdxStart = 0;
Modified: ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java?rev=696336&r1=696335&r2=696336&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPath.java Wed Sep 17 08:11:28 2008
@@ -54,6 +54,26 @@
this(path, SelectorUtils.tokenizePathAsArray(path));
}
+ /**
+ * Creates a new path as a child of another path.
+ *
+ * @param parent the parent path
+ * @param child the child, must not contain the file separator
+ */
+ public TokenizedPath(TokenizedPath parent, String child) {
+ if (parent.path.length() > 0
+ && parent.path.charAt(parent.path.length() - 1)
+ != File.separatorChar) {
+ path = parent.path + File.separatorChar + child;
+ } else {
+ path = parent.path + child;
+ }
+ tokenizedPath = new String[parent.tokenizedPath.length + 1];
+ System.arraycopy(parent.tokenizedPath, 0, tokenizedPath, 0,
+ parent.tokenizedPath.length);
+ tokenizedPath[parent.tokenizedPath.length] = child;
+ }
+
/* package */ TokenizedPath(String path, String[] tokens) {
this.path = path;
this.tokenizedPath = tokens;
Modified: ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java
URL: http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java?rev=696336&r1=696335&r2=696336&view=diff
==============================================================================
--- ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java (original)
+++ ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/TokenizedPattern.java Wed Sep 17 08:11:28 2008
@@ -31,6 +31,12 @@
*/
public class TokenizedPattern {
+ /**
+ * Instance that holds no tokens at all.
+ */
+ public static final TokenizedPattern EMPTY_PATTERN =
+ new TokenizedPattern("", new String[0]);
+
private final String pattern;
private final String tokenizedPattern[];
@@ -77,6 +83,22 @@
}
/**
+ * Tests whether or not a given path matches a given pattern.
+ *
+ * @param str The path to match, as a String. Must not be
+ * <code>null</code>.
+ * @param isCaseSensitive Whether or not matching should be performed
+ * case sensitively.
+ *
+ * @return <code>true</code> if the pattern matches against the string,
+ * or <code>false</code> otherwise.
+ */
+ public boolean matchPath(TokenizedPath path, boolean isCaseSensitive) {
+ return SelectorUtils.matchPath(tokenizedPattern, path.getTokens(),
+ isCaseSensitive);
+ }
+
+ /**
* Tests whether or not this pattern matches the start of
* a path.
*/
@@ -153,4 +175,31 @@
System.arraycopy(tokenizedPattern, 0, newPats, 0, newLen);
return new TokenizedPath(sb.toString(), newPats);
}
+
+ /**
+ * true if the last token equals the given string.
+ */
+ public boolean endsWith(String s) {
+ return tokenizedPattern.length > 0
+ && tokenizedPattern[tokenizedPattern.length - 1].equals(s);
+ }
+
+ /**
+ * Returns a new pattern without the last token of this pattern.
+ */
+ public TokenizedPattern withoutLastToken() {
+ if (tokenizedPattern.length == 0) {
+ throw new IllegalStateException("cant strip a token from nothing");
+ } else if (tokenizedPattern.length == 1) {
+ return EMPTY_PATTERN;
+ } else {
+ String toStrip = tokenizedPattern[tokenizedPattern.length - 1];
+ int index = pattern.lastIndexOf(toStrip);
+ String[] tokens = new String[tokenizedPattern.length - 1];
+ System.arraycopy(tokenizedPattern, 0, tokens, 0,
+ tokenizedPattern.length - 1);
+ return new TokenizedPattern(pattern.substring(0, index), tokens);
+ }
+ }
+
}