diff --git a/WHATSNEW b/WHATSNEW index 9adbfcea3..69f542b50 100644 --- a/WHATSNEW +++ b/WHATSNEW @@ -1,4 +1,4 @@ -Changes from Ant 1.7.x TO current SVN version +eol-styleChanges from Ant 1.7.x TO current SVN version ============================================= Changes that could break older environments: @@ -158,8 +158,6 @@ Fixed bugs: filter tokens Bugzilla Report 44226. - * Enhance performance of Project.fireMessageLoggedEvent - Bugzilla Report 45651. Other changes: -------------- @@ -274,6 +272,9 @@ Other changes: expression. Bugzilla Report 45284 + * Enhanced performance of Project.fireMessageLoggedEvent and DirectoryScanner + Bugzilla Report 45651 & 45665 + * The package list location for offline links can now be specified as an URL. Bugzilla Report 28881 diff --git a/src/main/org/apache/tools/ant/DirectoryScanner.java b/src/main/org/apache/tools/ant/DirectoryScanner.java index 98f0c6722..8c7dda9e8 100644 --- a/src/main/org/apache/tools/ant/DirectoryScanner.java +++ b/src/main/org/apache/tools/ant/DirectoryScanner.java @@ -34,6 +34,7 @@ import org.apache.tools.ant.types.Resource; import org.apache.tools.ant.types.ResourceFactory; import org.apache.tools.ant.types.resources.FileResource; import org.apache.tools.ant.types.selectors.FileSelector; +import org.apache.tools.ant.types.selectors.PathPattern; import org.apache.tools.ant.types.selectors.SelectorScanner; import org.apache.tools.ant.types.selectors.SelectorUtils; import org.apache.tools.ant.util.FileUtils; @@ -319,10 +320,8 @@ public class DirectoryScanner *

Gets lazily initialized on the first invocation of * isIncluded or isExcluded and cleared at the end of the scan * method (cleared in clearCaches, actually).

- * - * @since Ant 1.6.3 */ - private String[] includePatterns; + private PathPattern[] includePatterns; /** * Array of all exclude patterns that contain wildcards. @@ -330,10 +329,8 @@ public class DirectoryScanner *

Gets lazily initialized on the first invocation of * isIncluded or isExcluded and cleared at the end of the scan * method (cleared in clearCaches, actually).

- * - * @since Ant 1.6.3 */ - private String[] excludePatterns; + private PathPattern[] excludePatterns; /** * Have the non-pattern sets and pattern arrays for in- and @@ -1196,7 +1193,7 @@ public class DirectoryScanner return true; } for (int i = 0; i < includePatterns.length; i++) { - if (matchPath(includePatterns[i], name, isCaseSensitive())) { + if (includePatterns[i].matchPath(name, isCaseSensitive())) { return true; } } @@ -1296,7 +1293,7 @@ public class DirectoryScanner return true; } for (int i = 0; i < excludePatterns.length; i++) { - if (matchPath(excludePatterns[i], name, isCaseSensitive())) { + if (excludePatterns[i].matchPath(name, isCaseSensitive())) { return true; } } @@ -1696,18 +1693,17 @@ public class DirectoryScanner * @param patterns String[] of patterns. * @since Ant 1.6.3 */ - private String[] fillNonPatternSet(Set set, String[] patterns) { + private PathPattern[] fillNonPatternSet(Set set, String[] patterns) { ArrayList al = new ArrayList(patterns.length); for (int i = 0; i < patterns.length; i++) { if (!SelectorUtils.hasWildcards(patterns[i])) { set.add(isCaseSensitive() ? patterns[i] : patterns[i].toUpperCase()); } else { - al.add(patterns[i]); + al.add(new PathPattern(patterns[i])); } } - return set.size() == 0 ? patterns - : (String[]) al.toArray(new String[al.size()]); + return (PathPattern[]) al.toArray(new PathPattern[al.size()]); } } diff --git a/src/main/org/apache/tools/ant/types/selectors/PathPattern.java b/src/main/org/apache/tools/ant/types/selectors/PathPattern.java new file mode 100644 index 000000000..ae031c9f8 --- /dev/null +++ b/src/main/org/apache/tools/ant/types/selectors/PathPattern.java @@ -0,0 +1,82 @@ +/* + * Licensed to the Apache Software Foundation (ASF) under one or more + * contributor license agreements. See the NOTICE file distributed with + * this work for additional information regarding copyright ownership. + * The ASF licenses this file to You under the Apache License, Version 2.0 + * (the "License"); you may not use this file except in compliance with + * the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, software + * distributed under the License is distributed on an "AS IS" BASIS, + * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. + * See the License for the specific language governing permissions and + * limitations under the License. + * + */ + +package org.apache.tools.ant.types.selectors; + +/** + * 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 + */ +public class PathPattern { + + private final String pattern; + private final String tokenizedPattern[]; + + /** + * Initialize the PathPattern by parsing it. + * @param pattern The pattern to match against. Must not be + * null. + */ + public PathPattern(String pattern) { + this.pattern = pattern; + this.tokenizedPattern = SelectorUtils.tokenizePathAsArray(pattern); + } + + /** + * Tests whether or not a given path matches a given pattern. + * + * @param str The path to match, as a String. Must not be + * null. + * + * @return true if the pattern matches against the string, + * or false otherwise. + */ + public boolean matchPath(String str) { + return SelectorUtils.matchPath(tokenizedPattern, str, true); + } + + /** + * Tests whether or not a given path matches a given pattern. + * + * @param str The path to match, as a String. Must not be + * null. + * @param isCaseSensitive Whether or not matching should be performed + * case sensitively. + * + * @return true if the pattern matches against the string, + * or false otherwise. + */ + public boolean matchPath(String str, boolean isCaseSensitive) { + return SelectorUtils.matchPath(tokenizedPattern, str, isCaseSensitive); + } + + /** + * @return The pattern String + */ + public String toString() { + return pattern; + } + + public String getPattern() { + return 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 1fd7378f6..b4e1de1e3 100644 --- a/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java +++ b/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java @@ -38,7 +38,7 @@ import org.apache.tools.ant.types.resources.FileResource; */ public final class SelectorUtils { - private static SelectorUtils instance = new SelectorUtils(); + private static final SelectorUtils instance = new SelectorUtils(); private static final FileUtils FILE_UTILS = FileUtils.getFileUtils(); /** @@ -144,6 +144,11 @@ public final class SelectorUtils { /** * Tests whether or not a given path matches a given pattern. * + * If you need to call this method multiple times with the same + * pattern you should rather use PathPattern + * + * @see PathPattern + * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be @@ -153,12 +158,18 @@ public final class SelectorUtils { * or false otherwise. */ public static boolean matchPath(String pattern, String str) { - return matchPath(pattern, str, true); + String[] patDirs = tokenizePathAsArray(pattern); + return matchPath(patDirs, str, true); } /** * Tests whether or not a given path matches a given pattern. + * + * If you need to call this method multiple times with the same + * pattern you should rather use PathPattern * + * @see PathPattern + * * @param pattern The pattern to match against. Must not be * null. * @param str The path to match, as a String. Must not be @@ -172,22 +183,28 @@ public final class SelectorUtils { public static boolean matchPath(String pattern, String str, boolean isCaseSensitive) { String[] patDirs = tokenizePathAsArray(pattern); + return matchPath(patDirs, str, isCaseSensitive); + } + + /** + * Core implementation of matchPath. It is isolated so that it can be called from + * PathPattern. + */ + static boolean matchPath(String[] tokenizedPattern, String str, boolean isCaseSensitive) { String[] strDirs = tokenizePathAsArray(str); int patIdxStart = 0; - int patIdxEnd = patDirs.length - 1; + int patIdxEnd = tokenizedPattern.length - 1; int strIdxStart = 0; int strIdxEnd = strDirs.length - 1; // up to first '**' while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) { - String patDir = patDirs[patIdxStart]; + String patDir = tokenizedPattern[patIdxStart]; if (patDir.equals("**")) { break; } if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) { - patDirs = null; - strDirs = null; return false; } patIdxStart++; @@ -196,9 +213,7 @@ public final class SelectorUtils { if (strIdxStart > strIdxEnd) { // String is exhausted for (int i = patIdxStart; i <= patIdxEnd; i++) { - if (!patDirs[i].equals("**")) { - patDirs = null; - strDirs = null; + if (!tokenizedPattern[i].equals("**")) { return false; } } @@ -206,21 +221,17 @@ public final class SelectorUtils { } else { if (patIdxStart > patIdxEnd) { // String not exhausted, but pattern is. Failure. - patDirs = null; - strDirs = null; return false; } } // up to last '**' while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) { - String patDir = patDirs[patIdxEnd]; + String patDir = tokenizedPattern[patIdxEnd]; if (patDir.equals("**")) { break; } if (!match(patDir, strDirs[strIdxEnd], isCaseSensitive)) { - patDirs = null; - strDirs = null; return false; } patIdxEnd--; @@ -229,9 +240,7 @@ public final class SelectorUtils { if (strIdxStart > strIdxEnd) { // String is exhausted for (int i = patIdxStart; i <= patIdxEnd; i++) { - if (!patDirs[i].equals("**")) { - patDirs = null; - strDirs = null; + if (!tokenizedPattern[i].equals("**")) { return false; } } @@ -241,7 +250,7 @@ public final class SelectorUtils { while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) { int patIdxTmp = -1; for (int i = patIdxStart + 1; i <= patIdxEnd; i++) { - if (patDirs[i].equals("**")) { + if (tokenizedPattern[i].equals("**")) { patIdxTmp = i; break; } @@ -259,7 +268,7 @@ public final class SelectorUtils { strLoop: for (int i = 0; i <= strLength - patLength; i++) { for (int j = 0; j < patLength; j++) { - String subPat = patDirs[patIdxStart + j + 1]; + String subPat = tokenizedPattern[patIdxStart + j + 1]; String subStr = strDirs[strIdxStart + i + j]; if (!match(subPat, subStr, isCaseSensitive)) { continue strLoop; @@ -271,8 +280,6 @@ public final class SelectorUtils { } if (foundIdx == -1) { - patDirs = null; - strDirs = null; return false; } @@ -281,9 +288,7 @@ public final class SelectorUtils { } for (int i = patIdxStart; i <= patIdxEnd; i++) { - if (!patDirs[i].equals("**")) { - patDirs = null; - strDirs = null; + if (!tokenizedPattern[i].equals("**")) { return false; } } @@ -507,7 +512,7 @@ public final class SelectorUtils { /** * Same as {@link #tokenizePath tokenizePath} but hopefully faster. */ - private static String[] tokenizePathAsArray(String path) { + /*package*/ static String[] tokenizePathAsArray(String path) { String root = null; if (FileUtils.isAbsolutePath(path)) { String[] s = FILE_UTILS.dissect(path);