Author: gscokart
Date: Thu Aug 21 07:18:59 2008
New Revision: 687768

URL: http://svn.apache.org/viewvc?rev=687768&view=rev
Log:
Enhance performance of DirectoryScanner by parsing the patterns only once.  
Introduce a PathPattern to do that. (# 44226)

Added:
    
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/PathPattern.java   
(with props)
Modified:
    ant/core/trunk/WHATSNEW
    ant/core/trunk/src/main/org/apache/tools/ant/DirectoryScanner.java
    
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java

Modified: ant/core/trunk/WHATSNEW
URL: 
http://svn.apache.org/viewvc/ant/core/trunk/WHATSNEW?rev=687768&r1=687767&r2=687768&view=diff
==============================================================================
--- ant/core/trunk/WHATSNEW (original)
+++ ant/core/trunk/WHATSNEW Thu Aug 21 07:18:59 2008
@@ -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 @@
    filter tokens
    Bugzilla Report 44226.
    
- * Enhance performance of Project.fireMessageLoggedEvent  
-   Bugzilla Report 45651.
 
 Other changes:
 --------------
@@ -274,6 +272,9 @@
    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

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=687768&r1=687767&r2=687768&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 Thu Aug 
21 07:18:59 2008
@@ -34,6 +34,7 @@
 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 @@
      * <p>Gets lazily initialized on the first invocation of
      * isIncluded or isExcluded and cleared at the end of the scan
      * method (cleared in clearCaches, actually).</p>
-     *
-     * @since Ant 1.6.3
      */
-    private String[] includePatterns;
+    private PathPattern[] includePatterns;
 
     /**
      * Array of all exclude patterns that contain wildcards.
@@ -330,10 +329,8 @@
      * <p>Gets lazily initialized on the first invocation of
      * isIncluded or isExcluded and cleared at the end of the scan
      * method (cleared in clearCaches, actually).</p>
-     *
-     * @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 @@
             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 @@
             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 @@
      * @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()]);
     }
 
 }

Added: 
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/PathPattern.java
URL: 
http://svn.apache.org/viewvc/ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/PathPattern.java?rev=687768&view=auto
==============================================================================
--- 
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/PathPattern.java 
(added)
+++ 
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/PathPattern.java 
Thu Aug 21 07:18:59 2008
@@ -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
+    *                <code>null</code>.
+    */
+    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
+     *                <code>null</code>.
+     *                
+     * @return <code>true</code> if the pattern matches against the string,
+     *         or <code>false</code> 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
+     *                <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(String str, boolean isCaseSensitive) {
+        return SelectorUtils.matchPath(tokenizedPattern, str, isCaseSensitive);
+    }
+    
+    /**
+     * @return The pattern String
+     */
+    public String toString() {
+        return pattern;
+    }
+    
+    public String getPattern() {
+        return pattern;
+    }
+}

Propchange: 
ant/core/trunk/src/main/org/apache/tools/ant/types/selectors/PathPattern.java
------------------------------------------------------------------------------
    svn:eol-style = native

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=687768&r1=687767&r2=687768&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 
Thu Aug 21 07:18:59 2008
@@ -38,7 +38,7 @@
  */
 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 @@
     /**
      * 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
      *                <code>null</code>.
      * @param str     The path to match, as a String. Must not be
@@ -153,12 +158,18 @@
      *         or <code>false</code> 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
      *                <code>null</code>.
      * @param str     The path to match, as a String. Must not be
@@ -172,22 +183,28 @@
     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 @@
         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 @@
         } 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 @@
         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 @@
         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 @@
             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 @@
                         }
 
             if (foundIdx == -1) {
-                patDirs = null;
-                strDirs = null;
                 return false;
             }
 
@@ -281,9 +288,7 @@
         }
 
         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 @@
     /**
      * Same as [EMAIL PROTECTED] #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);


Reply via email to