From c13dba6d524fe74b1518e3442429ba6e97592edd Mon Sep 17 00:00:00 2001 From: Stefan Bodewig Date: Mon, 15 Sep 2008 09:54:06 +0000 Subject: [PATCH] Avoid repeated tokenization, make DefaultExcludesTest happy. git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@695402 13f79535-47bb-0310-9956-ffa450edef68 --- .../apache/tools/ant/DirectoryScanner.java | 48 +++++++++---------- .../ant/types/selectors/PathPattern.java | 29 +++++++++++ .../ant/types/selectors/SelectorUtils.java | 37 ++++++++------ 3 files changed, 76 insertions(+), 38 deletions(-) diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index d971cf1c0..009bd3ee9 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -145,30 +145,30 @@ public class DirectoryScanner */ protected static final String[] DEFAULTEXCLUDES = { // Miscellaneous typical temporary files - SelectorUtils.DEEP_ROOT_MATCH + "*~", - SelectorUtils.DEEP_ROOT_MATCH + "#*#", - SelectorUtils.DEEP_ROOT_MATCH + ".#*", - SelectorUtils.DEEP_ROOT_MATCH + "%*%", - SelectorUtils.DEEP_ROOT_MATCH + "._*", + SelectorUtils.DEEP_TREE_MATCH + "/*~", + SelectorUtils.DEEP_TREE_MATCH + "/#*#", + SelectorUtils.DEEP_TREE_MATCH + "/.#*", + SelectorUtils.DEEP_TREE_MATCH + "/%*%", + SelectorUtils.DEEP_TREE_MATCH + "/._*", // CVS - SelectorUtils.DEEP_ROOT_MATCH + "CVS", - SelectorUtils.DEEP_ROOT_MATCH + "CVS" + SelectorUtils.DEEP_LEAVES_MATCH, - SelectorUtils.DEEP_ROOT_MATCH + ".cvsignore", + SelectorUtils.DEEP_TREE_MATCH + "/CVS", + SelectorUtils.DEEP_TREE_MATCH + "/CVS/" + SelectorUtils.DEEP_TREE_MATCH, + SelectorUtils.DEEP_TREE_MATCH + "/.cvsignore", // SCCS - SelectorUtils.DEEP_ROOT_MATCH + "SCCS", - SelectorUtils.DEEP_ROOT_MATCH + "SCCS" + SelectorUtils.DEEP_LEAVES_MATCH, + SelectorUtils.DEEP_TREE_MATCH + "/SCCS", + SelectorUtils.DEEP_TREE_MATCH + "/SCCS/" + SelectorUtils.DEEP_TREE_MATCH, // Visual SourceSafe - SelectorUtils.DEEP_ROOT_MATCH + "vssver.scc", + SelectorUtils.DEEP_TREE_MATCH + "/vssver.scc", // Subversion - SelectorUtils.DEEP_ROOT_MATCH + ".svn", - SelectorUtils.DEEP_ROOT_MATCH + ".svn" + SelectorUtils.DEEP_LEAVES_MATCH, + SelectorUtils.DEEP_TREE_MATCH + "/.svn", + SelectorUtils.DEEP_TREE_MATCH + "/.svn/" + SelectorUtils.DEEP_TREE_MATCH, // Mac - SelectorUtils.DEEP_ROOT_MATCH + ".DS_Store" + SelectorUtils.DEEP_TREE_MATCH + "/.DS_Store" }; /** @@ -1295,10 +1295,13 @@ public class DirectoryScanner * least one include pattern, or false otherwise. */ protected boolean couldHoldIncluded(String name) { + final PathPattern tokenizedName = new PathPattern(name); for (int i = 0; i < includes.length; i++) { - if (matchPatternStart(includes[i], name, isCaseSensitive()) + PathPattern tokenizedInclude = new PathPattern(includes[i]); + if (tokenizedName.matchPatternStartOf(tokenizedInclude, + isCaseSensitive()) && isMorePowerfulThanExcludes(name, includes[i]) - && isDeeper(includes[i], name)) { + && isDeeper(tokenizedInclude, tokenizedName)) { return true; } } @@ -1313,13 +1316,9 @@ public class DirectoryScanner * @return whether the pattern is deeper than the name. * @since Ant 1.6.3 */ - private boolean isDeeper(String pattern, String name) { - Vector p = SelectorUtils.tokenizePath(pattern); - if (!p.contains(SelectorUtils.DEEP_TREE_MATCH)) { - Vector n = SelectorUtils.tokenizePath(name); - return p.size() > n.size(); - } - return true; + private boolean isDeeper(PathPattern pattern, PathPattern name) { + return pattern.containsPattern(SelectorUtils.DEEP_TREE_MATCH) + || pattern.depth() > name.depth(); } /** @@ -1341,7 +1340,8 @@ public class DirectoryScanner */ private boolean isMorePowerfulThanExcludes(String name, String includepattern) { - String soughtexclude = name + SelectorUtils.DEEP_LEAVES_MATCH; + final String soughtexclude = + name + File.separatorChar + SelectorUtils.DEEP_TREE_MATCH; for (int counter = 0; counter < excludes.length; counter++) { if (excludes[counter].equals(soughtexclude)) { return false; diff --git a/src/main/org/apache/tools/ant/types/selectors/PathPattern.java b/src/main/org/apache/tools/ant/types/selectors/PathPattern.java index ae031c9f8..aa2e28fe7 100644 --- a/src/main/org/apache/tools/ant/types/selectors/PathPattern.java +++ b/src/main/org/apache/tools/ant/types/selectors/PathPattern.java @@ -69,6 +69,16 @@ public class PathPattern { return SelectorUtils.matchPath(tokenizedPattern, str, isCaseSensitive); } + /** + * Tests whether or not this PathPattern matches the start of + * another pattern. + */ + public boolean matchPatternStartOf(PathPattern other, + boolean caseSensitive) { + return SelectorUtils.matchPatternStart(other.tokenizedPattern, + tokenizedPattern, caseSensitive); + } + /** * @return The pattern String */ @@ -79,4 +89,23 @@ public class PathPattern { public String getPattern() { return pattern; } + + /** + * The depth (or length) of a pattern. + */ + public int depth() { + return tokenizedPattern.length; + } + + /** + * Does the tokenized pattern contain the given string? + */ + public boolean containsPattern(String pat) { + for (int i = 0; i < tokenizedPattern.length; i++) { + if (tokenizedPattern[i].equals(pat)) { + return true; + } + } + return false; + } } 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 a40f49d24..7a6da092a 100644 --- a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java +++ b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java @@ -44,20 +44,6 @@ public final class SelectorUtils { */ public static final String DEEP_TREE_MATCH = "**"; - /** - * The pattern that matches an arbitrary number of directories at - * the leaves. - * @since Ant 1.8.0 - */ - public static final String DEEP_LEAVES_MATCH = File.separatorChar + "**"; - - /** - * The pattern that matches an arbitrary number of directories at - * the root. - * @since Ant 1.8.0 - */ - public static final String DEEP_ROOT_MATCH = "**" + File.separatorChar; - private static final SelectorUtils instance = new SelectorUtils(); private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); @@ -126,7 +112,30 @@ public final class SelectorUtils { String[] patDirs = tokenizePathAsArray(pattern); String[] strDirs = tokenizePathAsArray(str); + return matchPatternStart(patDirs, strDirs, isCaseSensitive); + } + + /** + * Tests whether or not a given path matches the start of a given + * pattern up to the first "**". + *

+ * This is not a general purpose test and should only be used if you + * can live with false positives. For example, pattern=**\a + * and str=b will yield true. + * + * @param patDirs The tokenized pattern to match against. Must not be + * null. + * @param strDirs The tokenized path to match. Must not be + * null. + * @param isCaseSensitive Whether or not matching should be performed + * case sensitively. + * + * @return whether or not a given path matches the start of a given + * pattern up to the first "**". + */ + static boolean matchPatternStart(String[] patDirs, String[] strDirs, + boolean isCaseSensitive) { int patIdxStart = 0; int patIdxEnd = patDirs.length - 1; int strIdxStart = 0;