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 15:52:41 UTC
svn commit: r696298 - 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 06:52:40 2008
New Revision: 696298
URL: http://svn.apache.org/viewvc?rev=696298&view=rev
Log:
avoid some tokenization (should really pay of in the next iteration/s) and replace recursion with iteration in findFile/isSymLink - right now we lose memoization of File.list but I'll reintroduce this later.
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=696298&r1=696297&r2=696298&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 06:52:40 2008
@@ -186,12 +186,6 @@
/** Helper. */
private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
- /** iterations for case-sensitive scanning. */
- private static final boolean[] CS_SCAN_ONLY = new boolean[] {true};
-
- /** iterations for non-case-sensitive scanning. */
- private static final boolean[] CS_THEN_NON_CS = new boolean[] {true, false};
-
/**
* Patterns which should be excluded by default.
*
@@ -901,25 +895,39 @@
* @since Ant 1.6
*/
private void checkIncludePatterns() {
+ ensureNonPatternSetsReady();
Map newroots = new HashMap();
// put in the newroots map the include patterns without
// wildcard tokens
+ int wildcardPatternIndex = 0;
for (int i = 0; i < includes.length; i++) {
+ boolean wildcards = SelectorUtils.hasWildcards(includes[i]);
if (FileUtils.isAbsolutePath(includes[i])) {
//skip abs. paths not under basedir, if set:
if (basedir != null
&& !SelectorUtils.matchPatternStart(includes[i],
basedir.getAbsolutePath(), isCaseSensitive())) {
+ if (wildcards) {
+ wildcardPatternIndex++;
+ }
continue;
}
} else if (basedir == null) {
//skip non-abs. paths if basedir == null:
+ if (wildcards) {
+ wildcardPatternIndex++;
+ }
continue;
}
- newroots.put(SelectorUtils.rtrimWildcardTokens(
- includes[i]), includes[i]);
+ if (wildcards) {
+ newroots.put(includePatterns[wildcardPatternIndex++]
+ .rtrimWildcardTokens(), includes[i]);
+ } else {
+ newroots.put(new TokenizedPath(includes[i]), includes[i]);
+ }
}
- if (newroots.containsKey("") && basedir != null) {
+ if (newroots.containsKey(TokenizedPath.EMPTY_PATH)
+ && basedir != null) {
// we are going to scan everything anyway
scandir(basedir, "", true);
} else {
@@ -937,12 +945,12 @@
}
while (it.hasNext()) {
Map.Entry entry = (Map.Entry) it.next();
- String currentelement = (String) entry.getKey();
+ TokenizedPath currentPath = (TokenizedPath) entry.getKey();
+ String currentelement = currentPath.toString();
if (basedir == null
&& !FileUtils.isAbsolutePath(currentelement)) {
continue;
}
- String originalpattern = (String) entry.getValue();
File myfile = new File(basedir, currentelement);
if (myfile.exists()) {
@@ -955,18 +963,24 @@
: FILE_UTILS.removeLeadingPath(canonBase,
getCanonicalFile(myfile));
if (!path.equals(currentelement) || ON_VMS) {
- myfile = findFile(basedir, currentelement, true);
+ myfile = currentPath.findFile(basedir, true);
if (myfile != null && basedir != null) {
currentelement = FILE_UTILS.removeLeadingPath(
basedir, myfile);
+ if (!currentPath.toString()
+ .equals(currentelement)) {
+ currentPath =
+ new TokenizedPath(currentelement);
+ }
}
}
} catch (IOException ex) {
throw new BuildException(ex);
}
}
+
if ((myfile == null || !myfile.exists()) && !isCaseSensitive()) {
- File f = findFile(basedir, currentelement, false);
+ File f = currentPath.findFile(basedir, false);
if (f != null && f.exists()) {
// adapt currentelement to the case we've
// actually found
@@ -974,11 +988,12 @@
? f.getAbsolutePath()
: FILE_UTILS.removeLeadingPath(basedir, f);
myfile = f;
+ currentPath = new TokenizedPath(currentelement);
}
}
+
if (myfile != null && myfile.exists()) {
- if (!followSymlinks
- && isSymlink(basedir, currentelement)) {
+ if (!followSymlinks && currentPath.isSymlink(basedir)) {
continue;
}
if (myfile.isDirectory()) {
@@ -997,6 +1012,7 @@
scandir(myfile, currentelement, true);
}
} else {
+ String originalpattern = (String) entry.getValue();
boolean included = isCaseSensitive()
? originalpattern.equals(currentelement)
: originalpattern.equalsIgnoreCase(currentelement);
@@ -1642,110 +1658,6 @@
}
/**
- * From <code>base</code> traverse the filesystem in order to find
- * a file that matches the given name.
- *
- * @param base base File (dir).
- * @param path file path.
- * @param cs whether to scan case-sensitively.
- * @return File object that points to the file in question or null.
- *
- * @since Ant 1.6.3
- */
- private File findFile(File base, String path, boolean cs) {
- if (FileUtils.isAbsolutePath(path)) {
- if (base == null) {
- String[] s = FILE_UTILS.dissect(path);
- base = new File(s[0]);
- path = s[1];
- } else {
- File f = FILE_UTILS.normalize(path);
- String s = FILE_UTILS.removeLeadingPath(base, f);
- if (s.equals(f.getAbsolutePath())) {
- //removing base from path yields no change; path
- //not child of base
- return null;
- }
- path = s;
- }
- }
- return findFile(base, SelectorUtils.tokenizePath(path), cs);
- }
-
- /**
- * From <code>base</code> traverse the filesystem in order to find
- * a file that matches the given stack of names.
- *
- * @param base base File (dir).
- * @param pathElements Vector of path elements (dirs...file).
- * @param cs whether to scan case-sensitively.
- * @return File object that points to the file in question or null.
- *
- * @since Ant 1.6.3
- */
- private File findFile(File base, Vector pathElements, boolean cs) {
- if (pathElements.size() == 0) {
- return base;
- }
- String current = (String) pathElements.remove(0);
- if (base == null) {
- return findFile(new File(current), pathElements, cs);
- }
- if (!base.isDirectory()) {
- return null;
- }
- String[] files = list(base);
- if (files == null) {
- throw new BuildException("IO error scanning directory "
- + base.getAbsolutePath());
- }
- boolean[] matchCase = cs ? CS_SCAN_ONLY : CS_THEN_NON_CS;
- for (int i = 0; i < matchCase.length; i++) {
- for (int j = 0; j < files.length; j++) {
- if (matchCase[i] ? files[j].equals(current)
- : files[j].equalsIgnoreCase(current)) {
- return findFile(new File(base, files[j]), pathElements, cs);
- }
- }
- }
- return null;
- }
-
- /**
- * Do we have to traverse a symlink when trying to reach path from
- * basedir?
- * @param base base File (dir).
- * @param path file path.
- * @since Ant 1.6
- */
- private boolean isSymlink(File base, String path) {
- return isSymlink(base, SelectorUtils.tokenizePath(path));
- }
-
- /**
- * Do we have to traverse a symlink when trying to reach path from
- * basedir?
- * @param base base File (dir).
- * @param pathElements Vector of path elements (dirs...file).
- * @since Ant 1.6
- */
- private boolean isSymlink(File base, Vector pathElements) {
- if (pathElements.size() > 0) {
- String current = (String) pathElements.remove(0);
- try {
- return FILE_UTILS.isSymbolicLink(base, current)
- || isSymlink(new File(base, current), pathElements);
- } catch (IOException ioe) {
- String msg = "IOException caught while checking "
- + "for links, couldn't get canonical path!";
- // will be caught and redirected to Ant's logging system
- System.err.println(msg);
- }
- }
- return false;
- }
-
- /**
* Has the directory with the given path relative to the base
* directory already been scanned?
*
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=696298&r1=696297&r2=696298&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 06:52:40 2008
@@ -698,18 +698,7 @@
* @return the leftmost part of the pattern without wildcards
*/
public static String rtrimWildcardTokens(String input) {
- String[] tokens = tokenizePathAsArray(input);
- StringBuffer sb = new StringBuffer();
- for (int i = 0; i < tokens.length; i++) {
- if (hasWildcards(tokens[i])) {
- break;
- }
- if (i > 0 && sb.charAt(sb.length() - 1) != File.separatorChar) {
- sb.append(File.separator);
- }
- sb.append(tokens[i]);
- }
- return sb.toString();
+ return new TokenizedPattern(input).rtrimWildcardTokens().toString();
}
}
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=696298&r1=696297&r2=696298&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 06:52:40 2008
@@ -18,12 +18,30 @@
package org.apache.tools.ant.types.selectors;
+import java.io.File;
+
+import org.apache.tools.ant.BuildException;
+import org.apache.tools.ant.util.FileUtils;
+
/**
* Container for a path that has been split into its components.
* @since 1.8.0
*/
public class TokenizedPath {
+ /**
+ * Instance that holds no tokens at all.
+ */
+ public static final TokenizedPath EMPTY_PATH =
+ new TokenizedPath("", new String[0]);
+
+ /** Helper. */
+ private static final FileUtils FILE_UTILS = FileUtils.getFileUtils();
+ /** iterations for case-sensitive scanning. */
+ private static final boolean[] CS_SCAN_ONLY = new boolean[] {true};
+ /** iterations for non-case-sensitive scanning. */
+ private static final boolean[] CS_THEN_NON_CS = new boolean[] {true, false};
+
private final String path;
private final String tokenizedPath[];
@@ -33,10 +51,14 @@
* <code>null</code>.
*/
public TokenizedPath(String path) {
- this.path = path;
- this.tokenizedPath = SelectorUtils.tokenizePathAsArray(path);
+ this(path, SelectorUtils.tokenizePathAsArray(path));
}
+ /* package */ TokenizedPath(String path, String[] tokens) {
+ this.path = path;
+ this.tokenizedPath = tokens;
+ }
+
/**
* @return The original path String
*/
@@ -54,4 +76,106 @@
/* package */ String[] getTokens() {
return tokenizedPath;
}
+
+ /**
+ * From <code>base</code> traverse the filesystem in order to find
+ * a file that matches the given name.
+ *
+ * @param base base File (dir).
+ * @param cs whether to scan case-sensitively.
+ * @return File object that points to the file in question or null.
+ */
+ public File findFile(File base, final boolean cs) {
+ String[] tokens = tokenizedPath;
+ if (FileUtils.isAbsolutePath(path)) {
+ if (base == null) {
+ String[] s = FILE_UTILS.dissect(path);
+ base = new File(s[0]);
+ tokens = SelectorUtils.tokenizePathAsArray(s[1]);
+ } else {
+ File f = FILE_UTILS.normalize(path);
+ String s = FILE_UTILS.removeLeadingPath(base, f);
+ if (s.equals(f.getAbsolutePath())) {
+ //removing base from path yields no change; path
+ //not child of base
+ return null;
+ }
+ tokens = SelectorUtils.tokenizePathAsArray(s);
+ }
+ }
+ return findFile(base, tokens, cs);
+ }
+
+ /**
+ * Do we have to traverse a symlink when trying to reach path from
+ * basedir?
+ * @param base base File (dir).
+ */
+ public boolean isSymlink(File base) {
+ for (int i = 0; i < tokenizedPath.length; i++) {
+ try {
+ if (FILE_UTILS.isSymbolicLink(base, tokenizedPath[i])) {
+ return true;
+ }
+ base = new File(base, tokenizedPath[i]);
+ } catch (java.io.IOException ioe) {
+ String msg = "IOException caught while checking "
+ + "for links, couldn't get canonical path!";
+ // will be caught and redirected to Ant's logging system
+ System.err.println(msg);
+ }
+ }
+ return false;
+ }
+
+ /**
+ * true if the original paths are equal.
+ */
+ public boolean equals(Object o) {
+ return o instanceof TokenizedPath
+ && path.equals(((TokenizedPath) o).path);
+ }
+
+ public int hashCode() {
+ return path.hashCode();
+ }
+
+ /**
+ * From <code>base</code> traverse the filesystem in order to find
+ * a file that matches the given stack of names.
+ *
+ * @param base base File (dir) - must not be null.
+ * @param pathElements array of path elements (dirs...file).
+ * @param cs whether to scan case-sensitively.
+ * @return File object that points to the file in question or null.
+ */
+ private static File findFile(File base, final String[] pathElements,
+ final boolean cs) {
+ for (int current = 0; current < pathElements.length; current++) {
+ if (!base.isDirectory()) {
+ return null;
+ }
+ String[] files = base.list();
+ if (files == null) {
+ throw new BuildException("IO error scanning directory "
+ + base.getAbsolutePath());
+ }
+ boolean found = false;
+ boolean[] matchCase = cs ? CS_SCAN_ONLY : CS_THEN_NON_CS;
+ for (int i = 0; !found && i < matchCase.length; i++) {
+ for (int j = 0; !found && j < files.length; j++) {
+ if (matchCase[i]
+ ? files[j].equals(pathElements[current])
+ : files[j].equalsIgnoreCase(pathElements[current])) {
+ base = new File(base, files[j]);
+ found = true;
+ }
+ }
+ }
+ if (!found) {
+ return null;
+ }
+ }
+ return pathElements.length == 0 && !base.isDirectory() ? null : base;
+ }
}
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=696298&r1=696297&r2=696298&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 06:52:40 2008
@@ -18,13 +18,16 @@
package org.apache.tools.ant.types.selectors;
+import java.io.File;
+
/**
- * Provides reusable path pattern matching. PathPattern is preferable to equivalent
- * SelectorUtils methods if you need to execute multiple matching with the same pattern
- * because here the pattern itself will be parsed only once.
+ * Provides reusable path pattern matching. PathPattern is preferable
+ * to equivalent SelectorUtils methods if you need to execute multiple
+ * matching with the same pattern because here the pattern itself will
+ * be parsed only once.
* @see SelectorUtils#matchPath(String, String)
* @see SelectorUtils#matchPath(String, String, boolean)
- * @since 1.8
+ * @since 1.8.0
*/
public class TokenizedPattern {
@@ -37,10 +40,14 @@
* <code>null</code>.
*/
public TokenizedPattern(String pattern) {
- this.pattern = pattern;
- this.tokenizedPattern = SelectorUtils.tokenizePathAsArray(pattern);
+ this(pattern, SelectorUtils.tokenizePathAsArray(pattern));
}
+ private TokenizedPattern(String pattern, String[] tokens) {
+ this.pattern = pattern;
+ this.tokenizedPattern = tokens;
+ }
+
/**
* Tests whether or not a given path matches a given pattern.
*
@@ -91,6 +98,18 @@
}
/**
+ * true if the original patterns are equal.
+ */
+ public boolean equals(Object o) {
+ return o instanceof TokenizedPattern
+ && pattern.equals(((TokenizedPattern) o).pattern);
+ }
+
+ public int hashCode() {
+ return pattern.hashCode();
+ }
+
+ /**
* The depth (or length) of a pattern.
*/
public int depth() {
@@ -108,4 +127,30 @@
}
return false;
}
+
+ /**
+ * Returns a new TokenizedPath where all tokens of this pattern to
+ * the right containing wildcards have been removed
+ * @return the leftmost part of the pattern without wildcards
+ */
+ public TokenizedPath rtrimWildcardTokens() {
+ StringBuffer sb = new StringBuffer();
+ int newLen = 0;
+ for (; newLen < tokenizedPattern.length; newLen++) {
+ if (SelectorUtils.hasWildcards(tokenizedPattern[newLen])) {
+ break;
+ }
+ if (newLen > 0
+ && sb.charAt(sb.length() - 1) != File.separatorChar) {
+ sb.append(File.separator);
+ }
+ sb.append(tokenizedPattern[newLen]);
+ }
+ if (newLen == 0) {
+ return TokenizedPath.EMPTY_PATH;
+ }
+ String[] newPats = new String[newLen];
+ System.arraycopy(tokenizedPattern, 0, newPats, 0, newLen);
+ return new TokenizedPath(sb.toString(), newPats);
+ }
}