ant-dev mailing list archives

Site index · List index
Message view « Date » · « Thread »
Top « Date » · « Thread »
From umag...@apache.org
Subject cvs commit: jakarta-ant/src/main/org/apache/tools/ant/types/selectors AndSelector.java BaseExtendSelector.java BaseSelector.java BaseSelectorContainer.java ContainsSelector.java DateSelector.java DependSelector.java DepthSelector.java ExtendFileSelector.java ExtendSelector.java FileSelector.java FilenameSelector.java MajoritySelector.java NoneSelector.java NotSelector.java OrSelector.java PresentSelector.java SelectorContainer.java SelectorScanner.java SelectorUtils.java SizeSelector.java
Date Tue, 30 Apr 2002 22:38:36 GMT
umagesh     02/04/30 15:38:36

  Modified:    .        WHATSNEW
               src/main/org/apache/tools/ant DirectoryScanner.java
               src/main/org/apache/tools/ant/types AbstractFileSet.java
  Added:       src/main/org/apache/tools/ant/types/selectors
                        AndSelector.java BaseExtendSelector.java
                        BaseSelector.java BaseSelectorContainer.java
                        ContainsSelector.java DateSelector.java
                        DependSelector.java DepthSelector.java
                        ExtendFileSelector.java ExtendSelector.java
                        FileSelector.java FilenameSelector.java
                        MajoritySelector.java NoneSelector.java
                        NotSelector.java OrSelector.java
                        PresentSelector.java SelectorContainer.java
                        SelectorScanner.java SelectorUtils.java
                        SizeSelector.java
  Log:
  Selectors feature to specify sophisticated selection criteria to create filesets.
  
  Got it in in the 11(and a half)th hour ;-)
  
  Submitted by: Bruce Atherton <bruce@callenish.com>
  
  Docs and testcases to follow in the next few days.
  
  Revision  Changes    Path
  1.263     +3 -0      jakarta-ant/WHATSNEW
  
  Index: WHATSNEW
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/WHATSNEW,v
  retrieving revision 1.262
  retrieving revision 1.263
  diff -u -r1.262 -r1.263
  --- WHATSNEW	30 Apr 2002 17:31:06 -0000	1.262
  +++ WHATSNEW	30 Apr 2002 22:38:35 -0000	1.263
  @@ -109,6 +109,9 @@
   
   Other changes:
   --------------
  +* Selector Elements now provide a way to create filesets based on 
  +  sophisticated selection criteria.
  +
   * Gzip and Bzip2 files can now be constructed in the fly when using
     the tar task without having to create the intermediate tar file on
     disk.  The Untar task can also untar GZip and BZip2 files on the fly
  
  
  
  1.25      +236 -420  jakarta-ant/src/main/org/apache/tools/ant/DirectoryScanner.java
  
  Index: DirectoryScanner.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/DirectoryScanner.java,v
  retrieving revision 1.24
  retrieving revision 1.25
  diff -u -r1.24 -r1.25
  --- DirectoryScanner.java	9 Apr 2002 15:27:07 -0000	1.24
  +++ DirectoryScanner.java	30 Apr 2002 22:38:35 -0000	1.25
  @@ -58,29 +58,37 @@
   import java.util.Vector;
   import java.util.StringTokenizer;
   
  +import org.apache.tools.ant.types.selectors.SelectorScanner;
  +import org.apache.tools.ant.types.selectors.FileSelector;
  +import org.apache.tools.ant.types.selectors.SelectorUtils;
  +
   /**
    * Class for scanning a directory for files/directories which match certain
    * criteria.
    * <p>
  - * These criteria consist of a set of include and exclude patterns. With these
  - * patterns, you can select which files you want to have included, and which
  - * files you want to have excluded.
  + * These criteria consist of selectors and patterns which have been specified.
  + * With the selectors you can select which files you want to have included.
  + * Files which are not selected are excluded. With patterns you can include
  + * or exclude files based on their filename.
    * <p>
    * The idea is simple. A given directory is recursively scanned for all files
  - * and directories. Each file/directory is matched against a set of include
  + * and directories. Each file/directory is matched against a set of selectors,
  + * including special support for matching against filenames with include and
    * and exclude patterns. Only files/directories which match at least one
  - * pattern of the include pattern list, and don't match any pattern of the
  - * exclude pattern list will be placed in the list of files/directories found.
  + * pattern of the include pattern list or other file selector, and don't match
  + * any pattern of the exclude pattern list or fail to match against a required
  + * selector will be placed in the list of files/directories found.
    * <p>
    * When no list of include patterns is supplied, "**" will be used, which
    * means that everything will be matched. When no list of exclude patterns is
  - * supplied, an empty list is used, such that nothing will be excluded.
  + * supplied, an empty list is used, such that nothing will be excluded. When
  + * no selectors are supplied, none are applied.
    * <p>
  - * The pattern matching is done as follows:
  + * The filename pattern matching is done as follows:
    * The name to be matched is split up in path segments. A path segment is the
    * name of a directory or file, which is bounded by
    * <code>File.separator</code> ('/' under UNIX, '\' under Windows).
  - * For example, "abc/def/ghi/xyz.java" is split up in the segments "abc", 
  + * For example, "abc/def/ghi/xyz.java" is split up in the segments "abc",
    * "def","ghi" and "xyz.java".
    * The same is done for the pattern against which should be matched.
    * <p>
  @@ -136,11 +144,12 @@
    * This will scan a directory called test for .class files, but excludes all
    * files in all proper subdirectories of a directory called "modules"
    *
  - * @author Arnout J. Kuiper 
  + * @author Arnout J. Kuiper
    * <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
    * @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a>
  + * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
    */
  -public class DirectoryScanner implements FileScanner {
  +public class DirectoryScanner implements FileScanner, SelectorScanner {
   
       /**
        * Patterns which should be excluded by default.
  @@ -170,36 +179,53 @@
       /** The patterns for the files to be excluded. */
       protected String[] excludes;
   
  -    /** The files which matched at least one include and no excludes. */
  +    /** Selectors that will filter which files are in our candidate list. */
  +    protected FileSelector[] selectors = null;
  +
  +    /** The files which matched at least one include and no excludes
  +     *  and were selected.
  +     */
       protected Vector filesIncluded;
   
  -    /** The files which did not match any includes. */
  +    /** The files which did not match any includes or selectors. */
       protected Vector filesNotIncluded;
   
  -    /** 
  -     * The files which matched at least one include and at least 
  +    /**
  +     * The files which matched at least one include and at least
        * one exclude.
        */
       protected Vector filesExcluded;
   
  -    /** The directories which matched at least one include and no excludes. */
  +    /** The directories which matched at least one include and no excludes
  +     *  and were selected.
  +     */
       protected Vector dirsIncluded;
   
       /** The directories which were found and did not match any includes. */
       protected Vector dirsNotIncluded;
   
  -    /** 
  -     * The directories which matched at least one include and at least one 
  +    /**
  +     * The directories which matched at least one include and at least one
        * exclude.
        */
       protected Vector dirsExcluded;
   
  +    /** The files which matched at least one include and no excludes and
  +     *  which a selector discarded.
  +     */
  +    protected Vector filesDeselected;
  +
  +    /** The directories which matched at least one include and no excludes
  +     *  but which a selector discarded.
  +     */
  +    protected Vector dirsDeselected;
  +
       /** Whether or not our results were built by a slow scan. */
       protected boolean haveSlowResults = false;
   
  -    /** 
  -     * Whether or not the file system should be treated as a case sensitive 
  -     * one. 
  +    /**
  +     * Whether or not the file system should be treated as a case sensitive
  +     * one.
        */
       protected boolean isCaseSensitive = true;
   
  @@ -213,241 +239,87 @@
       }
   
       /**
  -     * Tests whether or not a given path matches the start of a given 
  +     * Tests whether or not a given path matches the start of a given
        * pattern up to the first "**".
        * <p>
        * This is not a general purpose test and should only be used if you
  -     * can live with false positives. For example, <code>pattern=**\a</code> 
  +     * can live with false positives. For example, <code>pattern=**\a</code>
        * and <code>str=b</code> will yield <code>true</code>.
        *
  -     * @param pattern The pattern to match against. Must not be 
  +     * @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 
  +     * @param str     The path to match, as a String. Must not be
        *                <code>null</code>.
  -     * 
  -     * @return whether or not a given path matches the start of a given 
  +     *
  +     * @return whether or not a given path matches the start of a given
        * pattern up to the first "**".
        */
       protected static boolean matchPatternStart(String pattern, String str) {
  -        return matchPatternStart(pattern, str, true);
  +        return SelectorUtils.matchPatternStart(pattern, str);
       }
       /**
  -     * Tests whether or not a given path matches the start of a given 
  +     * Tests whether or not a given path matches the start of a given
        * pattern up to the first "**".
        * <p>
        * This is not a general purpose test and should only be used if you
  -     * can live with false positives. For example, <code>pattern=**\a</code> 
  +     * can live with false positives. For example, <code>pattern=**\a</code>
        * and <code>str=b</code> will yield <code>true</code>.
        *
  -     * @param pattern The pattern to match against. Must not be 
  +     * @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 
  +     * @param str     The path to match, as a String. Must not be
        *                <code>null</code>.
  -     * @param isCaseSensitive Whether or not matching should be performed 
  +     * @param isCaseSensitive Whether or not matching should be performed
        *                        case sensitively.
  -     * 
  -     * @return whether or not a given path matches the start of a given 
  +     *
  +     * @return whether or not a given path matches the start of a given
        * pattern up to the first "**".
        */
       protected static boolean matchPatternStart(String pattern, String str,
                                                  boolean isCaseSensitive) {
  -        // When str starts with a File.separator, pattern has to start with a
  -        // File.separator.
  -        // When pattern starts with a File.separator, str has to start with a
  -        // File.separator.
  -        if (str.startsWith(File.separator) !=
  -            pattern.startsWith(File.separator)) {
  -            return false;
  -        }
  -
  -        Vector patDirs = tokenizePath (pattern);
  -        Vector strDirs = tokenizePath (str);
  -
  -        int patIdxStart = 0;
  -        int patIdxEnd   = patDirs.size() - 1;
  -        int strIdxStart = 0;
  -        int strIdxEnd   = strDirs.size() - 1;
  -
  -        // up to first '**'
  -        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
  -            String patDir = (String) patDirs.elementAt(patIdxStart);
  -            if (patDir.equals("**")) {
  -                break;
  -            }
  -            if (!match(patDir, (String) strDirs.elementAt(strIdxStart), isCaseSensitive)) {
  -                return false;
  -            }
  -            patIdxStart++;
  -            strIdxStart++;
  -        }
  -
  -        if (strIdxStart > strIdxEnd) {
  -            // String is exhausted
  -            return true;
  -        } else if (patIdxStart > patIdxEnd) {
  -            // String not exhausted, but pattern is. Failure.
  -            return false;
  -        } else {
  -            // pattern now holds ** while string is not exhausted
  -            // this will generate false positives but we can live with that.
  -            return true;
  -        }
  +        return SelectorUtils.matchPatternStart(pattern, str, isCaseSensitive);
       }
   
       /**
        * Tests whether or not a given path matches a given pattern.
        *
  -     * @param pattern The pattern to match against. Must not be 
  +     * @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 
  +     * @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, 
  +     * @return <code>true</code> if the pattern matches against the string,
        *         or <code>false</code> otherwise.
        */
       protected static boolean matchPath(String pattern, String str) {
  -        return matchPath(pattern, str, true);
  +        return SelectorUtils.matchPath(pattern, str);
       }
   
       /**
        * Tests whether or not a given path matches a given pattern.
        *
  -     * @param pattern The pattern to match against. Must not be 
  +     * @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 
  +     * @param str     The path to match, as a String. Must not be
        *                <code>null</code>.
  -     * @param isCaseSensitive Whether or not matching should be performed 
  +     * @param isCaseSensitive Whether or not matching should be performed
        *                        case sensitively.
        *
  -     * @return <code>true</code> if the pattern matches against the string, 
  +     * @return <code>true</code> if the pattern matches against the string,
        *         or <code>false</code> otherwise.
        */
  -    protected static boolean matchPath(String pattern, String str, 
  +    protected static boolean matchPath(String pattern, String str,
                                          boolean isCaseSensitive) {
  -        // When str starts with a File.separator, pattern has to start with a
  -        // File.separator.
  -        // When pattern starts with a File.separator, str has to start with a
  -        // File.separator.
  -        if (str.startsWith(File.separator) !=
  -            pattern.startsWith(File.separator)) {
  -            return false;
  -        }
  -
  -        Vector patDirs = tokenizePath (pattern);
  -        Vector strDirs = tokenizePath (str);
  -
  -        int patIdxStart = 0;
  -        int patIdxEnd   = patDirs.size() - 1;
  -        int strIdxStart = 0;
  -        int strIdxEnd   = strDirs.size() - 1;
  -
  -        // up to first '**'
  -        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
  -            String patDir = (String) patDirs.elementAt(patIdxStart);
  -            if (patDir.equals("**")) {
  -                break;
  -            }
  -            if (!match(patDir, (String) strDirs.elementAt(strIdxStart), isCaseSensitive)) {
  -                return false;
  -            }
  -            patIdxStart++;
  -            strIdxStart++;
  -        }
  -        if (strIdxStart > strIdxEnd) {
  -            // String is exhausted
  -            for (int i = patIdxStart; i <= patIdxEnd; i++) {
  -                if (!patDirs.elementAt(i).equals("**")) {
  -                    return false;
  -                }
  -            }
  -            return true;
  -        } else {
  -            if (patIdxStart > patIdxEnd) {
  -                // String not exhausted, but pattern is. Failure.
  -                return false;
  -            }
  -        }
  -
  -        // up to last '**'
  -        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
  -            String patDir = (String) patDirs.elementAt(patIdxEnd);
  -            if (patDir.equals("**")) {
  -                break;
  -            }
  -            if (!match(patDir, (String) strDirs.elementAt(strIdxEnd), isCaseSensitive)) {
  -                return false;
  -            }
  -            patIdxEnd--;
  -            strIdxEnd--;
  -        }
  -        if (strIdxStart > strIdxEnd) {
  -            // String is exhausted
  -            for (int i = patIdxStart; i <= patIdxEnd; i++) {
  -                if (!patDirs.elementAt(i).equals("**")) {
  -                    return false;
  -                }
  -            }
  -            return true;
  -        }
  -
  -        while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
  -            int patIdxTmp = -1;
  -            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
  -                if (patDirs.elementAt(i).equals("**")) {
  -                    patIdxTmp = i;
  -                    break;
  -                }
  -            }
  -            if (patIdxTmp == patIdxStart + 1) {
  -                // '**/**' situation, so skip one
  -                patIdxStart++;
  -                continue;
  -            }
  -            // Find the pattern between padIdxStart & padIdxTmp in str between
  -            // strIdxStart & strIdxEnd
  -            int patLength = (patIdxTmp - patIdxStart - 1);
  -            int strLength = (strIdxEnd - strIdxStart + 1);
  -            int foundIdx  = -1;
  -strLoop:
  -            for (int i = 0; i <= strLength - patLength; i++) {
  -                for (int j = 0; j < patLength; j++) {
  -                    String subPat 
  -                        = (String) patDirs.elementAt(patIdxStart + j + 1);
  -                    String subStr 
  -                        = (String) strDirs.elementAt(strIdxStart + i + j);
  -                    if (!match(subPat, subStr, isCaseSensitive)) {
  -                        continue strLoop;
  -                    }
  -                }
  -
  -                foundIdx = strIdxStart + i;
  -                break;
  -            }
  -
  -            if (foundIdx == -1) {
  -                return false;
  -            }
  -
  -            patIdxStart = patIdxTmp;
  -            strIdxStart = foundIdx + patLength;
  -        }
  -
  -        for (int i = patIdxStart; i <= patIdxEnd; i++) {
  -            if (!patDirs.elementAt(i).equals("**")) {
  -                return false;
  -            }
  -        }
  -
  -        return true;
  +        return SelectorUtils.matchPath(pattern, str, isCaseSensitive);
       }
   
       /**
  -     * Tests whether or not a string matches against a pattern. 
  +     * Tests whether or not a string matches against a pattern.
        * The pattern may contain two special characters:<br>
        * '*' means zero or more characters<br>
        * '?' means one and only one character
  -     * 
  -     * @param pattern The pattern to match against. 
  +     *
  +     * @param pattern The pattern to match against.
        *                Must not be <code>null</code>.
        * @param str     The string which must be matched against the pattern.
        *                Must not be <code>null</code>.
  @@ -456,211 +328,62 @@
        *         or <code>false</code> otherwise.
        */
       public static boolean match(String pattern, String str) {
  -        return match(pattern, str, true);
  +        return SelectorUtils.match(pattern, str);
       }
   
       /**
  -     * Tests whether or not a string matches against a pattern. 
  +     * Tests whether or not a string matches against a pattern.
        * The pattern may contain two special characters:<br>
        * '*' means zero or more characters<br>
        * '?' means one and only one character
  -     * 
  -     * @param pattern The pattern to match against. 
  +     *
  +     * @param pattern The pattern to match against.
        *                Must not be <code>null</code>.
        * @param str     The string which must be matched against the pattern.
        *                Must not be <code>null</code>.
  -     * @param isCaseSensitive Whether or not matching should be performed 
  +     * @param isCaseSensitive Whether or not matching should be performed
        *                        case sensitively.
        *
        *
  -     * @return <code>true</code> if the string matches against the pattern, 
  +     * @return <code>true</code> if the string matches against the pattern,
        *         or <code>false</code> otherwise.
        */
  -    protected static boolean match(String pattern, String str, 
  +    protected static boolean match(String pattern, String str,
                                      boolean isCaseSensitive) {
  -        char[] patArr = pattern.toCharArray();
  -        char[] strArr = str.toCharArray();
  -        int patIdxStart = 0;
  -        int patIdxEnd   = patArr.length - 1;
  -        int strIdxStart = 0;
  -        int strIdxEnd   = strArr.length - 1;
  -        char ch;
  -
  -        boolean containsStar = false;
  -        for (int i = 0; i < patArr.length; i++) {
  -            if (patArr[i] == '*') {
  -                containsStar = true;
  -                break;
  -            }
  -        }
  -
  -        if (!containsStar) {
  -            // No '*'s, so we make a shortcut
  -            if (patIdxEnd != strIdxEnd) {
  -                return false; // Pattern and string do not have the same size
  -            }
  -            for (int i = 0; i <= patIdxEnd; i++) {
  -                ch = patArr[i];
  -                if (ch != '?') {
  -                    if (isCaseSensitive && ch != strArr[i]) {
  -                        return false;// Character mismatch
  -                    }
  -                    if (!isCaseSensitive && Character.toUpperCase(ch) !=
  -                        Character.toUpperCase(strArr[i])) {
  -                        return false; // Character mismatch
  -                    }
  -                }
  -            }
  -            return true; // String matches against pattern
  -        }
  -
  -        if (patIdxEnd == 0) {
  -            return true; // Pattern contains only '*', which matches anything
  -        }
  -
  -        // Process characters before first star
  -        while ((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
  -            if (ch != '?') {
  -                if (isCaseSensitive && ch != strArr[strIdxStart]) {
  -                    return false;// Character mismatch
  -                }
  -                if (!isCaseSensitive && Character.toUpperCase(ch) !=
  -                    Character.toUpperCase(strArr[strIdxStart])) {
  -                    return false;// Character mismatch
  -                }
  -            }
  -            patIdxStart++;
  -            strIdxStart++;
  -        }
  -        if (strIdxStart > strIdxEnd) {
  -            // All characters in the string are used. Check if only '*'s are
  -            // left in the pattern. If so, we succeeded. Otherwise failure.
  -            for (int i = patIdxStart; i <= patIdxEnd; i++) {
  -                if (patArr[i] != '*') {
  -                    return false;
  -                }
  -            }
  -            return true;
  -        }
  -
  -        // Process characters after last star
  -        while ((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
  -            if (ch != '?') {
  -                if (isCaseSensitive && ch != strArr[strIdxEnd]) {
  -                    return false;// Character mismatch
  -                }
  -                if (!isCaseSensitive && Character.toUpperCase(ch) !=
  -                    Character.toUpperCase(strArr[strIdxEnd])) {
  -                    return false;// Character mismatch
  -                }
  -            }
  -            patIdxEnd--;
  -            strIdxEnd--;
  -        }
  -        if (strIdxStart > strIdxEnd) {
  -            // All characters in the string are used. Check if only '*'s are
  -            // left in the pattern. If so, we succeeded. Otherwise failure.
  -            for (int i = patIdxStart; i <= patIdxEnd; i++) {
  -                if (patArr[i] != '*') {
  -                    return false;
  -                }
  -            }
  -            return true;
  -        }
  -
  -        // process pattern between stars. padIdxStart and patIdxEnd point
  -        // always to a '*'.
  -        while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
  -            int patIdxTmp = -1;
  -            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
  -                if (patArr[i] == '*') {
  -                    patIdxTmp = i;
  -                    break;
  -                }
  -            }
  -            if (patIdxTmp == patIdxStart + 1) {
  -                // Two stars next to each other, skip the first one.
  -                patIdxStart++;
  -                continue;
  -            }
  -            // Find the pattern between padIdxStart & padIdxTmp in str between
  -            // strIdxStart & strIdxEnd
  -            int patLength = (patIdxTmp - patIdxStart - 1);
  -            int strLength = (strIdxEnd - strIdxStart + 1);
  -            int foundIdx  = -1;
  -            strLoop:
  -            for (int i = 0; i <= strLength - patLength; i++) {
  -                for (int j = 0; j < patLength; j++) {
  -                    ch = patArr[patIdxStart + j + 1];
  -                    if (ch != '?') {
  -                        if (isCaseSensitive 
  -                             && ch != strArr[strIdxStart + i + j]) {
  -                            continue strLoop;
  -                        }
  -                        if (!isCaseSensitive && Character.toUpperCase(ch) !=
  -                            Character.toUpperCase(strArr[strIdxStart + i + j])) {
  -                            continue strLoop;
  -                        }
  -                    }
  -                }
  -
  -                foundIdx = strIdxStart + i;
  -                break;
  -            }
  -
  -            if (foundIdx == -1) {
  -                return false;
  -            }
  -
  -            patIdxStart = patIdxTmp;
  -            strIdxStart = foundIdx + patLength;
  -        }
  -
  -        // All characters in the string are used. Check if only '*'s are left
  -        // in the pattern. If so, we succeeded. Otherwise failure.
  -        for (int i = patIdxStart; i <= patIdxEnd; i++) {
  -            if (patArr[i] != '*') {
  -                return false;
  -            }
  -        }
  -        return true;
  +        return SelectorUtils.match(pattern, str, isCaseSensitive);
       }
   
       /**
        * Breaks a path up into a Vector of path elements, tokenizing on
        * <code>File.separator</code>.
  -     * 
  +     *
        * @param path Path to tokenize. Must not be <code>null</code>.
  -     * 
  +     *
        * @return a Vector of path elements from the tokenized path
        */
       private static Vector tokenizePath (String path) {
  -        Vector ret = new Vector();
  -        StringTokenizer st = new StringTokenizer(path, File.separator);
  -        while (st.hasMoreTokens()) {
  -            ret.addElement(st.nextToken());
  -        }
  -        return ret;
  +        return SelectorUtils.tokenizePath(path);
       }
  -    
  +
       /**
        * Sets the base directory to be scanned. This is the directory which is
        * scanned recursively. All '/' and '\' characters are replaced by
        * <code>File.separatorChar</code>, so the separator used need not match
        * <code>File.separatorChar</code>.
        *
  -     * @param basedir The base directory to scan. 
  +     * @param basedir The base directory to scan.
        *                Must not be <code>null</code>.
        */
       public void setBasedir(String basedir) {
  -        setBasedir(new File(basedir.replace('/', File.separatorChar).replace('\\', File.separatorChar)));
  +        setBasedir(new File(basedir.replace('/', File.separatorChar).replace(
  +                '\\', File.separatorChar)));
       }
   
       /**
  -     * Sets the base directory to be scanned. This is the directory which is 
  +     * Sets the base directory to be scanned. This is the directory which is
        * scanned recursively.
        *
  -     * @param basedir The base directory for scanning. 
  +     * @param basedir The base directory for scanning.
        *                Should not be <code>null</code>.
        */
       public void setBasedir(File basedir) {
  @@ -668,7 +391,7 @@
       }
   
       /**
  -     * Returns the base directory to be scanned. 
  +     * Returns the base directory to be scanned.
        * This is the directory which is scanned recursively.
        *
        * @return the base directory to be scanned
  @@ -680,7 +403,7 @@
       /**
        * Sets whether or not the file system should be regarded as case sensitive.
        *
  -     * @param isCaseSensitive whether or not the file system should be 
  +     * @param isCaseSensitive whether or not the file system should be
        *                        regarded as a case sensitive one
        */
       public void setCaseSensitive(boolean isCaseSensitive) {
  @@ -688,16 +411,16 @@
       }
   
       /**
  -     * Sets the list of include patterns to use. All '/' and '\' characters 
  -     * are replaced by <code>File.separatorChar</code>, so the separator used 
  +     * Sets the list of include patterns to use. All '/' and '\' characters
  +     * are replaced by <code>File.separatorChar</code>, so the separator used
        * need not match <code>File.separatorChar</code>.
        * <p>
        * When a pattern ends with a '/' or '\', "**" is appended.
        *
        * @param includes A list of include patterns.
  -     *                 May be <code>null</code>, indicating that all files 
  +     *                 May be <code>null</code>, indicating that all files
        *                 should be included. If a non-<code>null</code>
  -     *                 list is given, all elements must be 
  +     *                 list is given, all elements must be
        * non-<code>null</code>.
        */
       public void setIncludes(String[] includes) {
  @@ -707,7 +430,8 @@
               this.includes = new String[includes.length];
               for (int i = 0; i < includes.length; i++) {
                   String pattern;
  -                pattern = includes[i].replace('/', File.separatorChar).replace('\\', File.separatorChar);
  +                pattern = includes[i].replace('/', File.separatorChar).replace(
  +                        '\\', File.separatorChar);
                   if (pattern.endsWith(File.separator)) {
                       pattern += "**";
                   }
  @@ -716,16 +440,17 @@
           }
       }
   
  +
       /**
  -     * Sets the list of exclude patterns to use. All '/' and '\' characters 
  -     * are replaced by <code>File.separatorChar</code>, so the separator used 
  +     * Sets the list of exclude patterns to use. All '/' and '\' characters
  +     * are replaced by <code>File.separatorChar</code>, so the separator used
        * need not match <code>File.separatorChar</code>.
        * <p>
        * When a pattern ends with a '/' or '\', "**" is appended.
        *
  -     * @param excludes A list of exclude patterns. 
  -     *                 May be <code>null</code>, indicating that no files 
  -     *                 should be excluded. If a non-<code>null</code> list is 
  +     * @param excludes A list of exclude patterns.
  +     *                 May be <code>null</code>, indicating that no files
  +     *                 should be excluded. If a non-<code>null</code> list is
        *                 given, all elements must be non-<code>null</code>.
        */
       public void setExcludes(String[] excludes) {
  @@ -735,7 +460,8 @@
               this.excludes = new String[excludes.length];
               for (int i = 0; i < excludes.length; i++) {
                   String pattern;
  -                pattern = excludes[i].replace('/', File.separatorChar).replace('\\', File.separatorChar);
  +                pattern = excludes[i].replace('/', File.separatorChar).replace(
  +                        '\\', File.separatorChar);
                   if (pattern.endsWith(File.separator)) {
                       pattern += "**";
                   }
  @@ -744,11 +470,22 @@
           }
       }
   
  +
  +    /**
  +     * Sets the selectors that will select the filelist.
  +     *
  +     * @param selectors specifies the selectors to be invoked on a scan
  +     */
  +    public void setSelectors(FileSelector[] selectors) {
  +        this.selectors = selectors;
  +    }
  +
  +
       /**
        * Returns whether or not the scanner has included all the files or
        * directories it has come across so far.
        *
  -     * @return <code>true</code> if all files and directories which have 
  +     * @return <code>true</code> if all files and directories which have
        *         been found so far have been included.
        */
       public boolean isEverythingIncluded() {
  @@ -757,9 +494,10 @@
   
       /**
        * Scans the base directory for files which match at least one include
  -     * pattern and don't match any exclude patterns.
  +     * pattern and don't match any exclude patterns. If there are selectors
  +     * then the files must pass muster there, as well.
        *
  -     * @exception IllegalStateException if the base directory was set 
  +     * @exception IllegalStateException if the base directory was set
        *            incorrectly (i.e. if it is <code>null</code>, doesn't exist,
        *            or isn't a directory).
        */
  @@ -788,13 +526,19 @@
           filesIncluded    = new Vector();
           filesNotIncluded = new Vector();
           filesExcluded    = new Vector();
  +        filesDeselected  = new Vector();
           dirsIncluded     = new Vector();
           dirsNotIncluded  = new Vector();
           dirsExcluded     = new Vector();
  +        dirsDeselected   = new Vector();
   
           if (isIncluded("")) {
               if (!isExcluded("")) {
  -                dirsIncluded.addElement("");
  +                if (isSelected("",basedir)) {
  +                    dirsIncluded.addElement("");
  +                } else {
  +                    dirsDeselected.addElement("");
  +                }
               } else {
                   dirsExcluded.addElement("");
               }
  @@ -806,8 +550,8 @@
   
       /**
        * Top level invocation for a slow scan. A slow scan builds up a full
  -     * list of excluded/included files/directories, whereas a fast scan 
  -     * will only have full results for included files, as it ignores 
  +     * list of excluded/included files/directories, whereas a fast scan
  +     * will only have full results for included files, as it ignores
        * directories which can't possibly hold any included files/directories.
        * <p>
        * Returns immediately if a slow scan has already been completed.
  @@ -843,12 +587,12 @@
       /**
        * Scans the given directory for files and directories. Found files and
        * directories are placed in their respective collections, based on the
  -     * matching of includes and excludes. When a directory is found, it is
  -     * scanned recursively.
  +     * 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 vpath The path relative to the base directory (needed to 
  -     *              prevent problems with an absolute path when using 
  +     * @param vpath 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.
        *
  @@ -881,10 +625,19 @@
               if (file.isDirectory()) {
                   if (isIncluded(name)) {
                       if (!isExcluded(name)) {
  -                        dirsIncluded.addElement(name);
  -                        if (fast) {
  -                            scandir(file, name + File.separator, fast);
  +                        if (isSelected(name,file)) {
  +                            dirsIncluded.addElement(name);
  +                            if (fast) {
  +                                scandir(file, name + File.separator, fast);
  +                            }
  +                        } else {
  +                            everythingIncluded = false;
  +                            dirsDeselected.addElement(name);
  +                            if (fast && couldHoldIncluded(name)) {
  +                                scandir(file, name + File.separator, fast);
  +                            }
                           }
  +
                       } else {
                           everythingIncluded = false;
                           dirsExcluded.addElement(name);
  @@ -905,7 +658,12 @@
               } else if (file.isFile()) {
                   if (isIncluded(name)) {
                       if (!isExcluded(name)) {
  -                        filesIncluded.addElement(name);
  +                        if (isSelected(name,file)) {
  +                            filesIncluded.addElement(name);
  +                        } else {
  +                            everythingIncluded = false;
  +                            filesDeselected.addElement(name);
  +                        }
                       } else {
                           everythingIncluded = false;
                           filesExcluded.addElement(name);
  @@ -919,7 +677,7 @@
       }
   
       /**
  -     * Tests whether or not a name matches against at least one include 
  +     * Tests whether or not a name matches against at least one include
        * pattern.
        *
        * @param name The name to match. Must not be <code>null</code>.
  @@ -936,11 +694,11 @@
       }
   
       /**
  -     * Tests whether or not a name matches the start of at least one include 
  +     * Tests whether or not a name matches the start of 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 the start of at 
  +     * @return <code>true</code> when the name matches against the start of at
        *         least one include pattern, or <code>false</code> otherwise.
        */
       protected boolean couldHoldIncluded(String name) {
  @@ -953,7 +711,7 @@
       }
   
       /**
  -     * Tests whether or not a name matches against at least one exclude 
  +     * Tests whether or not a name matches against at least one exclude
        * pattern.
        *
        * @param name The name to match. Must not be <code>null</code>.
  @@ -970,7 +728,26 @@
       }
   
       /**
  -     * Returns the names of the files which matched at least one of the 
  +     * Tests whether a name should be selected.
  +     *
  +     * @param name the filename to check for selecting
  +     * @param file the java.io.File object for this filename
  +     * @return <code>false</code> when the selectors says that the file
  +     *         should not be selected, <code>true</code> otherwise.
  +     */
  +    protected boolean isSelected(String name, File file) {
  +        if (selectors != null) {
  +            for (int i = 0; i < selectors.length; i++) {
  +                if ((selectors[i].isSelected(basedir, name, file)) == false) {
  +                    return false;
  +                }
  +            }
  +        }
  +        return true;
  +    }
  +
  +    /**
  +     * Returns the names of the files which matched at least one of the
        * include patterns and none of the exclude patterns.
        * The names are relative to the base directory.
        *
  @@ -981,19 +758,19 @@
           int count = filesIncluded.size();
           String[] files = new String[count];
           for (int i = 0; i < count; i++) {
  -            files[i] = (String) filesIncluded.elementAt(i);
  +            files[i] = (String)filesIncluded.elementAt(i);
           }
           return files;
       }
   
       /**
  -     * Returns the names of the files which matched none of the include 
  +     * Returns the names of the files which matched none of the include
        * patterns. The names are relative to the base directory. This involves
        * performing a slow scan if one has not already been completed.
        *
  -     * @return the names of the files which matched none of the include 
  +     * @return the names of the files which matched none of the include
        *         patterns.
  -     * 
  +     *
        * @see #slowScan
        */
       public String[] getNotIncludedFiles() {
  @@ -1001,20 +778,20 @@
           int count = filesNotIncluded.size();
           String[] files = new String[count];
           for (int i = 0; i < count; i++) {
  -            files[i] = (String) filesNotIncluded.elementAt(i);
  +            files[i] = (String)filesNotIncluded.elementAt(i);
           }
           return files;
       }
   
       /**
  -     * Returns the names of the files which matched at least one of the 
  +     * Returns the names of the files which matched at least one of the
        * include patterns and at least one of the exclude patterns.
        * The names are relative to the base directory. This involves
        * performing a slow scan if one has not already been completed.
        *
  -     * @return the names of the files which matched at least one of the 
  +     * @return the names of the files which matched at least one of the
        *         include patterns and at at least one of the exclude patterns.
  -     * 
  +     *
        * @see #slowScan
        */
       public String[] getExcludedFiles() {
  @@ -1022,13 +799,32 @@
           int count = filesExcluded.size();
           String[] files = new String[count];
           for (int i = 0; i < count; i++) {
  -            files[i] = (String) filesExcluded.elementAt(i);
  +            files[i] = (String)filesExcluded.elementAt(i);
  +        }
  +        return files;
  +    }
  +
  +    /**
  +     * Returns the names of the files which were selected. The names
  +     * are relative to the base directory. This involves performing
  +     * a slow scan if one has not already been completed.
  +     *
  +     * @return the names of the files which were selected.
  +     *
  +     * @see #slowScan
  +     */
  +    public String[] getDeselectedFiles() {
  +        slowScan();
  +        int count = filesDeselected.size();
  +        String[] files = new String[count];
  +        for (int i = 0; i < count; i++) {
  +            files[i] = (String)filesDeselected.elementAt(i);
           }
           return files;
       }
   
       /**
  -     * Returns the names of the directories which matched at least one of the 
  +     * Returns the names of the directories which matched at least one of the
        * include patterns and none of the exclude patterns.
        * The names are relative to the base directory.
        *
  @@ -1039,7 +835,7 @@
           int count = dirsIncluded.size();
           String[] directories = new String[count];
           for (int i = 0; i < count; i++) {
  -            directories[i] = (String) dirsIncluded.elementAt(i);
  +            directories[i] = (String)dirsIncluded.elementAt(i);
           }
           return directories;
       }
  @@ -1051,7 +847,7 @@
        *
        * @return the names of the directories which matched none of the include
        * patterns.
  -     * 
  +     *
        * @see #slowScan
        */
       public String[] getNotIncludedDirectories() {
  @@ -1059,20 +855,20 @@
           int count = dirsNotIncluded.size();
           String[] directories = new String[count];
           for (int i = 0; i < count; i++) {
  -            directories[i] = (String) dirsNotIncluded.elementAt(i);
  +            directories[i] = (String)dirsNotIncluded.elementAt(i);
           }
           return directories;
       }
   
       /**
  -     * Returns the names of the directories which matched at least one of the 
  +     * Returns the names of the directories which matched at least one of the
        * include patterns and at least one of the exclude patterns.
        * The names are relative to the base directory. This involves
        * performing a slow scan if one has not already been completed.
  -     * 
  -     * @return the names of the directories which matched at least one of the 
  +     *
  +     * @return the names of the directories which matched at least one of the
        * include patterns and at least one of the exclude patterns.
  -     * 
  +     *
        * @see #slowScan
        */
       public String[] getExcludedDirectories() {
  @@ -1080,7 +876,26 @@
           int count = dirsExcluded.size();
           String[] directories = new String[count];
           for (int i = 0; i < count; i++) {
  -            directories[i] = (String) dirsExcluded.elementAt(i);
  +            directories[i] = (String)dirsExcluded.elementAt(i);
  +        }
  +        return directories;
  +    }
  +
  +    /**
  +     * Returns the names of the directories which were selected. The names
  +     * are relative to the base directory. This involves performing a
  +     * slow scan if one has not already been completed.
  +     *
  +     * @return the names of the directories which were selected.
  +     *
  +     * @see #slowScan
  +     */
  +    public String[] getDeselectedDirectories() {
  +        slowScan();
  +        int count = dirsDeselected.size();
  +        String[] directories = new String[count];
  +        for (int i = 0; i < count; i++) {
  +            directories[i] = (String)dirsDeselected.elementAt(i);
           }
           return directories;
       }
  @@ -1096,7 +911,8 @@
               System.arraycopy(excludes, 0, newExcludes, 0, excludesLength);
           }
           for (int i = 0; i < DEFAULTEXCLUDES.length; i++) {
  -            newExcludes[i + excludesLength] = DEFAULTEXCLUDES[i].replace('/', File.separatorChar).replace('\\', File.separatorChar);
  +            newExcludes[i + excludesLength] = DEFAULTEXCLUDES[i].replace('/',
  +                    File.separatorChar).replace('\\', File.separatorChar);
           }
           excludes = newExcludes;
       }
  
  
  
  1.5       +181 -23   jakarta-ant/src/main/org/apache/tools/ant/types/AbstractFileSet.java
  
  Index: AbstractFileSet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-ant/src/main/org/apache/tools/ant/types/AbstractFileSet.java,v
  retrieving revision 1.4
  retrieving revision 1.5
  diff -u -r1.4 -r1.5
  --- AbstractFileSet.java	15 Apr 2002 12:11:50 -0000	1.4
  +++ AbstractFileSet.java	30 Apr 2002 22:38:35 -0000	1.5
  @@ -57,6 +57,7 @@
   import org.apache.tools.ant.FileScanner;
   import org.apache.tools.ant.DirectoryScanner;
   import org.apache.tools.ant.Project;
  +import org.apache.tools.ant.types.selectors.*;
   
   import java.io.File;
   import java.util.Stack;
  @@ -70,23 +71,26 @@
    *
    * <p>Common base class for DirSet and FileSet.</p>
    *
  - * @author <a href="mailto:ajkuiper@wxs.nl">Arnout J. Kuiper</a> 
  + * @author <a href="mailto:ajkuiper@wxs.nl">Arnout J. Kuiper</a>
    * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
    * @author <a href="mailto:rubys@us.ibm.com">Sam Ruby</a>
    * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a>
    * @author <a href="mailto:stefan.bodewig@epost.de">Stefan Bodewig</a>
    * @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a>
  + * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
    */
  -public abstract class AbstractFileSet extends DataType implements Cloneable {
  -    
  +public abstract class AbstractFileSet extends DataType implements Cloneable,
  +        SelectorContainer {
  +
       private PatternSet defaultPatterns = new PatternSet();
       private Vector additionalPatterns = new Vector();
  +    private Vector selectors = new Vector();
   
       private File dir;
       private boolean useDefaultExcludes = true;
       private boolean isCaseSensitive = true;
   
  -   
  +
       public AbstractFileSet() {
           super();
       }
  @@ -104,7 +108,7 @@
        * Makes this instance in effect a reference to another instance.
        *
        * <p>You must not set another attribute or nest elements inside
  -     * this element if you make it a reference.</p> 
  +     * this element if you make it a reference.</p>
        */
       public void setRefid(Reference r) throws BuildException {
           if (dir != null || defaultPatterns.hasPatterns()) {
  @@ -158,7 +162,7 @@
           }
           return defaultPatterns.createInclude();
       }
  -    
  +
       /**
        * add a name entry on the include files list
        */
  @@ -168,7 +172,7 @@
           }
           return defaultPatterns.createIncludesFile();
       }
  -    
  +
       /**
        * add a name entry on the exclude list
        */
  @@ -188,7 +192,7 @@
           }
           return defaultPatterns.createExcludesFile();
       }
  -    
  +
       /**
        * Appends <code>includes</code> to the current list of include
        * patterns.
  @@ -224,7 +228,7 @@
       /**
        * Sets the name of the file containing the includes patterns.
        *
  -     * @param incl The file to fetch the include patterns from.  
  +     * @param incl The file to fetch the include patterns from.
        */
        public void setIncludesfile(File incl) throws BuildException {
            if (isReference()) {
  @@ -237,7 +241,7 @@
       /**
        * Sets the name of the file containing the includes patterns.
        *
  -     * @param excl The file to fetch the exclude patterns from.  
  +     * @param excl The file to fetch the exclude patterns from.
        */
        public void setExcludesfile(File excl) throws BuildException {
            if (isReference()) {
  @@ -250,7 +254,7 @@
       /**
        * Sets whether default exclusions should be used or not.
        *
  -     * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions 
  +     * @param useDefaultExcludes "true"|"on"|"yes" when default exclusions
        *                           should be used, "false"|"off"|"no" when they
        *                           shouldn't be used.
        */
  @@ -272,8 +276,8 @@
           this.isCaseSensitive = isCaseSensitive;
       }
   
  -    
  -    
  +
  +
       /**
        * sets the name used for this datatype instance.
        */
  @@ -290,14 +294,14 @@
                   }
               }
           }
  -            
  +
           String classname = getClass().getName();
  -        
  +
           int dotIndex = classname.lastIndexOf(".");
           if (dotIndex == -1) {
               return classname;
           }
  -        return classname.substring(dotIndex + 1); 
  +        return classname.substring(dotIndex + 1);
       }
   
       /**
  @@ -326,12 +330,12 @@
           ds.scan();
           return ds;
       }
  -    
  +
       public void setupDirectoryScanner(FileScanner ds, Project p) {
           if (ds == null) {
               throw new IllegalArgumentException("ds cannot be null");
           }
  -        
  +
           ds.setBasedir(dir);
   
           final int count = additionalPatterns.size();
  @@ -340,11 +344,16 @@
               defaultPatterns.append((PatternSet) o, p);
           }
   
  -        p.log(getDataTypeName() + ": Setup scanner in dir " + dir + 
  +        p.log(getDataTypeName() + ": Setup scanner in dir " + dir +
               " with " + defaultPatterns, Project.MSG_DEBUG);
  -        
  +
           ds.setIncludes(defaultPatterns.getIncludePatterns(p));
           ds.setExcludes(defaultPatterns.getExcludePatterns(p));
  +        if (ds instanceof SelectorScanner) {
  +            SelectorScanner ss = (SelectorScanner)ds;
  +            ss.setSelectors(getSelectors(p));
  +        }
  +
           if (useDefaultExcludes) {
               ds.addDefaultExcludes();
           }
  @@ -353,7 +362,7 @@
   
       /**
        * Performs the check for circular references and returns the
  -     * referenced FileSet.  
  +     * referenced FileSet.
        */
       protected AbstractFileSet getRef(Project p) {
           if (!checked) {
  @@ -361,15 +370,164 @@
               stk.push(this);
               dieOnCircularReference(stk, p);
           }
  -        
  +
           Object o = ref.getReferencedObject(p);
           if (!getClass().isAssignableFrom(o.getClass())) {
  -            String msg = ref.getRefId() + " doesn\'t denote a " 
  +            String msg = ref.getRefId() + " doesn\'t denote a "
                   + getDataTypeName();
               throw new BuildException(msg);
           } else {
               return (AbstractFileSet) o;
           }
  +    }
  +
  +    // SelectorContainer methods
  +
  +    /**
  +     * Indicates whether there are any selectors here.
  +     *
  +     * @return whether any selectors are in this container
  +     */
  +    public boolean hasSelectors() {
  +        return !(selectors.isEmpty());
  +    }
  +
  +    /**
  +     * Gives the count of the number of selectors in this container
  +     *
  +     * @return the number of selectors in this container
  +     */
  +    public int selectorCount() {
  +        return selectors.size();
  +    }
  +
  +    /**
  +     * Returns the set of selectors as an array.
  +     *
  +     * @return an array of selectors in this container
  +     */
  +    public FileSelector[] getSelectors(Project p) {
  +        if (isReference()) {
  +            return getRef(p).getSelectors(p);
  +        } else {
  +            FileSelector[] result = new FileSelector[selectors.size()];
  +            selectors.copyInto(result);
  +            return result;
  +        }
  +    }
  +
  +    /**
  +     * Returns an enumerator for accessing the set of selectors.
  +     *
  +     * @return an enumerator that goes through each of the selectors
  +     */
  +    public Enumeration selectorElements() {
  +        return selectors.elements();
  +    }
  +
  +    /**
  +     * Add a new selector into this container.
  +     *
  +     * @param selector the new selector to add
  +     */
  +    public void appendSelector(FileSelector selector) {
  +        if (isReference()) {
  +            throw noChildrenAllowed();
  +        }
  +        selectors.addElement(selector);
  +    }
  +
  +    /* Methods below all implement the static selectors */
  +
  +    /**
  +     * add an "And" selector entry on the selector list
  +     */
  +    public void addAnd(AndSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add an "Or" selector entry on the selector list
  +     */
  +    public void addOr(OrSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a "Not" selector entry on the selector list
  +     */
  +    public void addNot(NotSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a "None" selector entry on the selector list
  +     */
  +    public void addNone(NoneSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a majority selector entry on the selector list
  +     */
  +    public void addMajority(MajoritySelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a selector date entry on the selector list
  +     */
  +    public void addDateselect(DateSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a selector size entry on the selector list
  +     */
  +    public void addSizeselect(SizeSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a selector filename entry on the selector list
  +     */
  +    public void addFilenameselect(FilenameSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add an extended selector entry on the selector list
  +     */
  +    public void addExtendSelect(ExtendSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a contains selector entry on the selector list
  +     */
  +    public void addContainsSelect(ContainsSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a present selector entry on the selector list
  +     */
  +    public void addPresentSelect(PresentSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a depth selector entry on the selector list
  +     */
  +    public void addDepthSelect(DepthSelector selector) {
  +        appendSelector(selector);
  +    }
  +
  +    /**
  +     * add a depends selector entry on the selector list
  +     */
  +    public void addDependSelect(DependSelector selector) {
  +        appendSelector(selector);
       }
   
   }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/AndSelector.java
  
  Index: AndSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.Enumeration;
  
  /**
   * This selector has a collection of other selectors, all of which have to
   * select a file in order for this selector to select it.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class AndSelector extends BaseSelectorContainer {
  
      /**
       * Default constructor.
       */
      public AndSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer();
          if (hasSelectors()) {
              buf.append("{andselect: ");
              buf.append(super.toString());
              buf.append("}");
          }
          return buf.toString();
      }
  
      /**
       * Returns true (the file is selected) only if all other selectors
       * agree that the file should be selected.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename the name of the file to check
       * @param file a java.io.File object for the filename that the selector
       * can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
          validate();
          Enumeration e = selectorElements();
          boolean result;
  
          while(e.hasMoreElements()) {
              result = ((FileSelector)e.nextElement()).isSelected(basedir,
                      filename,file);
              if (!result) {
                  return false;
              }
          }
          return true;
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/BaseExtendSelector.java
  
  Index: BaseExtendSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.types.DataType;
  import org.apache.tools.ant.types.Parameter;
  
  
  /**
   * Convenience base class for all selectors accessed through ExtendSelector.
   * It provides support for gathering the parameters together as well as for
   * assigning an error message and throwing a build exception if an error is
   * detected.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public abstract class BaseExtendSelector extends BaseSelector implements
          ExtendFileSelector {
  
      /** The passed in parameter array. */
      protected Parameter[] parameters = null;
  
      /**
       * Default constructor.
       */
      public BaseExtendSelector() {
      }
  
      /**
       * Set all the Parameters for this dynamic selector, collected by
       * the ExtendSelector class.
       *
       * @param parameters the complete set of parameters for this selector
       */
      public void setParameters(Parameter[] parameters) {
          this.parameters = parameters;
      }
  
      /**
       * Allows access to the parameters gathered and set within the
       * <extendselect> tag.
       *
       * @return the set of parameters defined for this selector
       */
      protected Parameter[] getParameters() {
          return parameters;
      }
  
      /**
       * Method that each selector will implement to create their
       * selection behaviour. If there is a problem with the setup
       * of a selector, it can throw a BuildException to indicate
       * the problem.
       *
       * @param basedir A java.io.File object for the base directory
       * @param filename The name of the file to check
       * @param file A File object for this filename
       * @return whether the file should be selected or not
       */
      public abstract boolean isSelected(File basedir, String filename,
                                         File file)
              throws BuildException;
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/BaseSelector.java
  
  Index: BaseSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.BuildException;
  import  org.apache.tools.ant.types.DataType;
  
  /**
   * A convenience base class that you can subclass Selectors from. It
   * provides some helpful common behaviour. Note that there is no need
   * for Selectors to inherit from this class, it is only necessary that
   * they implement FileSelector.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public abstract class BaseSelector extends DataType implements FileSelector {
  
      private String errmsg = null;
  
  
      /**
       * Do nothing constructor.
       */
      public BaseSelector() {
      }
  
      /**
       * Allows all selectors to indicate a setup error. Note that only
       * the first error message is recorded.
       *
       * @param msg The error message any BuildException should throw.
       */
      public void setError(String msg) {
          if (errmsg == null) {
              errmsg = msg;
          }
      }
  
      /**
       * Returns any error messages that have been set.
       *
       * @return the error condition
       */
      public String getError() {
          return errmsg;
      }
  
  
      /**
       * <p>Subclasses can override this method to provide checking of their
       * state. So long as they call validate() from isSelected(), this will
       * be called automatically (unless they override validate()).</p>
       * <p>Implementations should check for incorrect settings and call
       * setError() as necessary.</p>
       */
      public void verifySettings() {
      }
  
  
  
      /**
       * Subclasses can use this to throw the requisite exception
       * in isSelected() in the case of an error condition.
       */
      public void validate() {
          verifySettings();
          if (getError() != null) {
              throw new BuildException(errmsg);
          }
      }
  
      /**
       * Method that each selector will implement to create their
       * selection behaviour. If there is a problem with the setup
       * of a selector, it can throw a BuildException to indicate
       * the problem.
       *
       * @param basedir A java.io.File object for the base directory
       * @param filename The name of the file to check
       * @param file A File object for this filename
       * @return whether the file should be selected or not
       */
      public abstract boolean isSelected(File basedir, String filename,
              File file);
  
  }
  
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/BaseSelectorContainer.java
  
  Index: BaseSelectorContainer.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.BuildException;
  import  org.apache.tools.ant.types.Reference;
  
  import java.io.File;
  import java.util.Enumeration;
  import java.util.Stack;
  import java.util.Vector;
  
  /**
   * This is the base class for selectors that can contain other selectors.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public abstract class BaseSelectorContainer extends BaseSelector
          implements SelectorContainer {
  
      private Vector selectorsList = new Vector();
  
      /**
       * Default constructor.
       */
      public BaseSelectorContainer() {
      }
  
      /**
       * Indicates whether there are any selectors here.
       */
      public boolean hasSelectors() {
          return !(selectorsList.isEmpty());
      }
  
      /**
       * Gives the count of the number of selectors in this container
       */
      public int selectorCount() {
          return selectorsList.size();
      }
  
      /**
       * Returns the set of selectors as an array.
       */
      public FileSelector[] getSelectors(Project p) {
          if (isReference()) {
              return getRef(p).getSelectors(p);
          } else {
              FileSelector[] result = new FileSelector[selectorsList.size()];
              selectorsList.copyInto(result);
              return result;
          }
      }
  
      /**
       * Returns an enumerator for accessing the set of selectors.
       */
      public Enumeration selectorElements() {
          return selectorsList.elements();
      }
  
      /**
       * Performs the check for circular references and returns the
       * referenced SelectorContainer.
       */
      private SelectorContainer getRef(Project p) {
          if (!checked) {
              Stack stk = new Stack();
              stk.push(this);
              dieOnCircularReference(stk, p);
          }
  
          Object o = ref.getReferencedObject(p);
          if (!(o instanceof SelectorContainer)) {
              throw new BuildException(ref.getRefId() +
                  " doesn\'t denote a selector type");
          } else {
              return (SelectorContainer) o;
          }
      }
  
      /**
       * Convert the Selectors within this container to a string. This will
       * just be a helper class for the subclasses that put their own name
       * around the contents listed here.
       *
       * @return comma separated list of Selectors contained in this one
       */
      public String toString() {
          StringBuffer buf = new StringBuffer();
          Enumeration e = selectorElements();
          if (e.hasMoreElements()) {
              while(e.hasMoreElements()) {
                  buf.append(e.nextElement().toString());
                  if (e.hasMoreElements()) {
                      buf.append(", ");
                  }
              }
          }
  
          return buf.toString();
      }
  
      /**
       * Add a new selector into this container.
       *
       * @param selector the new selector to add
       * @return the selector that was added
       */
      public void appendSelector(FileSelector selector) {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          selectorsList.addElement(selector);
      }
  
      /**
       * <p>This implementation validates the container by calling
       * verifySettings() and then validates each contained selector
       * provided that the selector implements the validate interface.
       * </p>
       * <p>Ordinarily, this will validate all the elements of a selector
       * container even if the isSelected() method of some elements is
       * never called. This has two effects:</p>
       * <ul>
       * <li>Validation will often occur twice.
       * <li>Since it is not required that selectors derive from
       * BaseSelector, there could be selectors in the container whose
       * error conditions are not detected if their isSelected() call
       * is never made.
       * </ul>
       */
      public void validate() {
          verifySettings();
          String errmsg = getError();
          if (errmsg != null) {
              throw new BuildException(errmsg);
          }
          Enumeration e = selectorElements();
          while(e.hasMoreElements()) {
              Object o = e.nextElement();
              if (o instanceof BaseSelector) {
                  ((BaseSelector)o).validate();
              }
          }
      }
  
  
      /**
       * Method that each selector will implement to create their selection
       * behaviour. This is what makes SelectorContainer abstract.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename the name of the file to check
       * @param file a java.io.File object for the filename that the selector
       * can use
       * @return whether the file should be selected or not
       */
      public abstract boolean isSelected(File basedir, String filename,
                                         File file);
  
  
      /* Methods below all implement the static selectors */
  
      /**
       * add an "And" selector entry on the selector list
       */
      public void addAnd(AndSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add an "Or" selector entry on the selector list
       */
      public void addOr(OrSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a "Not" selector entry on the selector list
       */
      public void addNot(NotSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a "None" selector entry on the selector list
       */
      public void addNone(NoneSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a majority selector entry on the selector list
       */
      public void addMajority(MajoritySelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a selector date entry on the selector list
       */
      public void addDateselect(DateSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a selector size entry on the selector list
       */
      public void addSizeselect(SizeSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a selector filename entry on the selector list
       */
      public void addFilenameselect(FilenameSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add an extended selector entry on the selector list
       */
      public void addExtendSelect(ExtendSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a contains selector entry on the selector list
       */
      public void addContainsSelect(ContainsSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a present selector entry on the selector list
       */
      public void addPresentSelect(PresentSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a depth selector entry on the selector list
       */
      public void addDepthSelect(DepthSelector selector) {
          appendSelector(selector);
      }
  
      /**
       * add a depends selector entry on the selector list
       */
      public void addDependSelect(DependSelector selector) {
          appendSelector(selector);
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/ContainsSelector.java
  
  Index: ContainsSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.io.BufferedReader;
  import java.io.InputStreamReader;
  import java.io.FileInputStream;
  import java.io.IOException;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Parameter;
  import org.apache.tools.ant.BuildException;
  
  /**
   * Selector that filters files based on whether they contain a
   * particular string.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class ContainsSelector extends BaseExtendSelector {
  
      private String contains = null;
      private boolean casesensitive = true;
      public final static String CONTAINS_KEY = "contains";
      public final static String CASE_KEY = "casesensitive";
  
  
      public ContainsSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer("{containsselector contains: ");
          buf.append(contains);
          buf.append(" casesensitive: ");
          if (casesensitive) {
              buf.append("true");
          } else {
              buf.append("false");
          }
          buf.append("}");
          return buf.toString();
      }
  
      /**
       * The string to search for within a file.
       *
       * @param contains the string that a file must contain to be selected.
       */
      public void setContains(String contains) {
          this.contains = contains;
      }
  
      /**
       * Whether to ignore case in the string being searched.
       *
       * @param casesensitive whether to pay attention to case sensitivity
       */
      public void setCasesensitive(boolean casesensitive) {
          this.casesensitive = casesensitive;
      }
  
      /**
       * When using this as a dynamic selector, this method will be called.
       * It translates each parameter into the appropriate setXXX() call.
       *
       * @param parameters the complete set of parameters for this selector
       */
      public void setParameters(Parameter[] parameters) {
          super.setParameters(parameters);
          if (parameters != null) {
              for (int i = 0; i < parameters.length; i++) {
                  String paramname = parameters[i].getName();
                  if (CONTAINS_KEY.equalsIgnoreCase(paramname)) {
                      setContains(parameters[i].getValue());
                  }
                  else if (CASE_KEY.equalsIgnoreCase(paramname)) {
                      setCasesensitive(Project.toBoolean(
                          parameters[i].getValue()));
                  }
                  else {
                      setError("Invalid parameter " + paramname);
                  }
              }
          }
      }
  
      /**
       * Checks to make sure all settings are kosher. In this case, it
       * means that the pattern attribute has been set.
       *
       */
      public void verifySettings() {
          if (contains == null) {
              setError("The contains attribute is required");
          }
      }
  
      /**
       * The heart of the matter. This is where the selector gets to decide
       * on the inclusion of a file in a particular fileset.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object the selector can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
  
          // throw BuildException on error
          validate();
  
          if (file.isDirectory()) {
              return true;
          }
  
          BufferedReader in = null;
          try {
              in = new BufferedReader(new InputStreamReader(
                      new FileInputStream(file)));
              String teststr = in.readLine();
              while (teststr != null) {
                  if (teststr.indexOf(contains) > -1) {
                      return true;
                  }
                  teststr = in.readLine();
              }
              return false;
          }
          catch (IOException ioe) {
              throw new BuildException("Could not read file " + filename);
          }
          finally {
              try {
                  in.close();
              }
              catch (Exception e) {
                  throw new BuildException("Could not close file " + filename);
              }
          }
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/DateSelector.java
  
  Index: DateSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.text.DateFormat;
  import java.text.ParseException;
  import java.util.Locale;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.EnumeratedAttribute;
  import org.apache.tools.ant.types.Parameter;
  
  /**
   * Selector that chooses files based on their last modified date.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class DateSelector extends BaseExtendSelector {
  
      private long millis = -1;
      private String dateTime = null;
      private boolean includeDirs = false;
      private int cmp = 0;
      public final static String MILLIS_KEY = "millis";
      public final static String DATETIME_KEY = "datetime";
      public final static String CHECKDIRS_KEY = "checkdirs";
      public final static String WHEN_KEY = "when";
  
      public DateSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer("{dateselector date: ");
          buf.append(dateTime);
          buf.append("compare: ");
          if (cmp == 0) {
              buf.append("before");
          }
          else if (cmp == 1) {
              buf.append("after");
          } else {
              buf.append("equal");
          }
          buf.append("}");
          return buf.toString();
      }
  
      /**
       * For users that prefer to express time in milliseconds since 1970
       *
       * @param millis the time to compare file's last modified date to,
       *        expressed in milliseconds
       */
      public void setMillis(long millis) {
          this.millis = millis;
      }
  
      /**
       * Sets the date. The user must supply it in MM/DD/YYYY HH:MM AM_PM
       * format
       *
       * @param dateTime a string in MM/DD/YYYY HH:MM AM_PM format
       */
      public void setDatetime(String dateTime) {
          this.dateTime = dateTime;
          if (dateTime != null) {
              DateFormat df = DateFormat.getDateTimeInstance(
                                                      DateFormat.SHORT,
                                                      DateFormat.SHORT,
                                                      Locale.US);
              try {
                  setMillis(df.parse(dateTime).getTime());
                  if (millis < 0) {
                      setError("Date of " + dateTime
                          + " results in negative milliseconds value relative"
                          + " to epoch (January 1, 1970, 00:00:00 GMT).");
                  }
              } catch (ParseException pe) {
                      setError("Date of " + dateTime
                          + " Cannot be parsed correctly. It should be in"
                          + " MM/DD/YYYY HH:MM AM_PM format.");
              }
          }
      }
  
      /**
       * Should we be checking dates on directories?
       *
       * @param includeDirs whether to check the timestamp on directories
       */
      public void setCheckdirs(boolean includeDirs) {
          this.includeDirs = includeDirs;
      }
  
      /**
       * Sets the type of comparison to be done on the file's last modified
       * date.
       *
       * @param cmp The comparison to perform, an EnumeratedAttribute
       */
      public void setWhen(TimeComparisons cmp) {
          this.cmp = cmp.getIndex();
      }
  
      /**
       * When using this as a dynamic selector, this method will be called.
       * It translates each parameter into the appropriate setXXX() call.
       *
       * @param parameters the complete set of parameters for this selector
       */
      public void setParameters(Parameter[] parameters) {
          super.setParameters(parameters);
          if (parameters != null) {
              for (int i = 0; i < parameters.length; i++) {
                  String paramname = parameters[i].getName();
                  if (MILLIS_KEY.equalsIgnoreCase(paramname)) {
                      try {
                          setMillis(new Long(parameters[i].getValue()
                                  ).longValue());
                      } catch (NumberFormatException nfe) {
                          setError("Invalid millisecond setting " +
                              parameters[i].getValue());
                      }
                  }
                  else if (DATETIME_KEY.equalsIgnoreCase(paramname)) {
                      setDatetime(parameters[i].getValue());
                  }
                  else if (CHECKDIRS_KEY.equalsIgnoreCase(paramname)) {
                      setCheckdirs(Project.toBoolean(parameters[i].getValue()));
                  }
                  else if (WHEN_KEY.equalsIgnoreCase(paramname)) {
                      TimeComparisons cmp = new TimeComparisons();
                      cmp.setValue(parameters[i].getValue());
                      setWhen(cmp);
                  }
                  else {
                      setError("Invalid parameter " + paramname);
                  }
              }
          }
      }
  
      /**
       * This is a consistency check to ensure the selector's required
       * values have been set.
       */
      public void verifySettings() {
          if (dateTime == null && millis < 0) {
              setError("You must provide a datetime or the number of "
                  + "milliseconds.");
          }
          else if (millis < 0) {
              setError("Date of " + dateTime
                  + " results in negative milliseconds"
                  + " value relative to epoch (January 1, 1970, 00:00:00 GMT).");
          }
      }
  
      /**
       * The heart of the matter. This is where the selector gets to decide
       * on the inclusion of a file in a particular fileset.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object the selector can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
          validate();
          if (file.isDirectory() && (includeDirs == false)) {
              return true;
          }
          if (cmp == 0) {
              return (file.lastModified() < millis);
          }
          else if (cmp == 1) {
              return (file.lastModified() > millis);
          }
          else {
              return (file.lastModified() == millis);
          }
      }
  
      /**
       * Enumerated attribute with the values for time comparison.
       * <p>
       */
      public static class TimeComparisons extends EnumeratedAttribute {
          public String[] getValues() {
              return new String[] {"before", "after", "equal"};
          }
      }
  
  }
  
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/DependSelector.java
  
  Index: DependSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Mapper;
  import org.apache.tools.ant.util.IdentityMapper;
  import org.apache.tools.ant.util.FileNameMapper;
  import org.apache.tools.ant.BuildException;
  
  /**
   * Selector that filters files based on whether they are newer than
   * a matching file in another directory tree. It can contain a mapper
   * element, so isn't available as an ExtendSelector (since those
   * parameters can't hold other elements).
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class DependSelector extends BaseSelector {
  
      private String targetdir = null;
      private File targetbase = null;
      private Mapper mapperElement = null;
      private FileNameMapper map = null;
      private int granularity = 0;
  
      public DependSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer("{dependselector targetdir: ");
          buf.append(targetdir);
          buf.append(" granularity: ");
          buf.append(granularity);
          if (map != null) {
              buf.append(" mapper: ");
              buf.append(map.toString());
          }
          else if (mapperElement != null) {
              buf.append(" mapper: ");
              buf.append(mapperElement.toString());
          }
          buf.append("}");
          return buf.toString();
      }
  
      /**
       * The name of the file or directory which is checked for out-of-date
       * files.
       *
       * @param targetdir the directory to scan looking for files.
       */
      public void setTargetdir(String targetdir) {
          this.targetdir = SelectorUtils.fixPath(targetdir);
          targetbase = new File(this.targetdir);
      }
  
      /**
       * Sets the number of milliseconds leeway we will give before we consider
       * a file out of date.
       */
      public void setGranularity(int granularity) {
          this.granularity = granularity;
      }
  
      /**
       * Defines the FileNameMapper to use (nested mapper element).
       */
      public Mapper createMapper() throws BuildException {
          if (mapperElement != null) {
              throw new BuildException("Cannot define more than one mapper");
          }
          mapperElement = new Mapper(project);
          return mapperElement;
      }
  
  
      /**
       * Checks to make sure all settings are kosher. In this case, it
       * means that the dest attribute has been set and we have a mapper.
       */
      public void verifySettings() {
          if (targetdir == null) {
              setError("The targetdir attribute is required.");
          }
          if (mapperElement == null) {
              map = new IdentityMapper();
          }
          else {
              map = mapperElement.getImplementation();
          }
          if (map == null) {
              setError("Could not set <mapper> element.");
          }
      }
  
      /**
       * The heart of the matter. This is where the selector gets to decide
       * on the inclusion of a file in a particular fileset.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object the selector can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
  
          // throw BuildException on error
          validate();
  
          // Get File object for the target directory
          File target = targetbase;
          if (target == null) {
              target = new File(basedir,targetdir);
          }
  
          // Determine file whose out-of-dateness is to be checked
          String[] destfiles = map.mapFileName(filename);
          // Sanity check
          if (destfiles.length != 1 || destfiles[0] == null) {
              throw new BuildException("Invalid destination file results for "
                  + targetdir + " with filename " + filename);
          }
          String destname = destfiles[0];
          File destfile = new File(target,destname);
  
          return SelectorUtils.isOutOfDate(file, destfile, granularity);
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/DepthSelector.java
  
  Index: DepthSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.StringTokenizer;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Parameter;
  import org.apache.tools.ant.BuildException;
  
  /**
   * Selector that filters files based on the how deep in the directory
   * tree they are.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class DepthSelector extends BaseExtendSelector {
  
      public int min = -1;
      public int max = -1;
      public final static String MIN_KEY = "min";
      public final static String MAX_KEY = "max";
  
      public DepthSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer("{depthselector min: ");
          buf.append(min);
          buf.append(" max: ");
          buf.append(max);
          buf.append("}");
          return buf.toString();
      }
  
      /**
       * The minimum depth below the basedir before a file is selected.
       *
       * @param min minimum directory levels below basedir to go
       */
      public void setMin(int min) {
          this.min = min;
      }
  
      /**
       * The minimum depth below the basedir before a file is selected.
       *
       * @param min maximum directory levels below basedir to go
       */
      public void setMax(int max) {
          this.max = max;
      }
  
      /**
       * When using this as a dynamic selector, this method will be called.
       * It translates each parameter into the appropriate setXXX() call.
       *
       * @param parameters the complete set of parameters for this selector
       */
      public void setParameters(Parameter[] parameters) {
          super.setParameters(parameters);
          if (parameters != null) {
              for (int i = 0; i < parameters.length; i++) {
                  String paramname = parameters[i].getName();
                  if (MIN_KEY.equalsIgnoreCase(paramname)) {
                      try {
                          setMin(Integer.parseInt(parameters[i].getValue()));
                      }
                      catch (NumberFormatException nfe1) {
                          setError("Invalid minimum value "
                              + parameters[i].getValue());
                      }
                  }
                  else if (MAX_KEY.equalsIgnoreCase(paramname)) {
                      try {
                          setMax(Integer.parseInt(parameters[i].getValue()));
                      }
                      catch (NumberFormatException nfe1) {
                          setError("Invalid maximum value "
                              + parameters[i].getValue());
                      }
                  }
                  else {
                      setError("Invalid parameter " + paramname);
                  }
              }
          }
      }
  
      /**
       * Checks to make sure all settings are kosher. In this case, it
       * means that the max depth is not lower than the min depth.
       */
      public void verifySettings() {
          if (min < 0 && max < 0) {
              setError("You must set at least one of the min or the " +
                      "max levels.");
          }
          if (max < min) {
              setError("The maximum depth is lower than the minimum.");
          }
      }
  
      /**
       * The heart of the matter. This is where the selector gets to decide
       * on the inclusion of a file in a particular fileset. Most of the work
       * for this selector is offloaded into SelectorUtils, a static class
       * that provides the same services for both FilenameSelector and
       * DirectoryScanner.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object the selector can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
  
          // throw BuildException on error
          validate();
  
          int depth = -1;
          // If you felt daring, you could cache the basedir absolute path
          String abs_base = basedir.getAbsolutePath();
          String abs_file = file.getAbsolutePath();
          StringTokenizer tok_base = new StringTokenizer(abs_base, File.separator);
          StringTokenizer tok_file = new StringTokenizer(abs_file, File.separator);
          while (tok_file.hasMoreTokens()) {
              String filetoken = tok_file.nextToken();
              if (tok_base.hasMoreTokens()) {
                  String basetoken = tok_base.nextToken();
                  // Sanity check. Ditch it if you want faster performance
                  if (!basetoken.equals(filetoken)) {
                      throw new BuildException("File " + filename +
                          " does not appear within " + abs_base + "directory");
                  }
              }
              else {
                  depth += 1;
                  if (max > -1 && depth > max) {
                      return false;
                  }
              }
          }
          if (tok_base.hasMoreTokens()) {
              throw new BuildException("File " + filename +
                  " is outside of " + abs_base + "directory tree");
          }
          if (min > -1 && depth < min) {
              return false;
          }
          return true;
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/ExtendFileSelector.java
  
  Index: ExtendFileSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  
  import org.apache.tools.ant.types.Parameterizable;
  
  /**
   * This is the interface to be used by all dynamic selectors, those that are
   * called through the <extendselect> tag. It is the amalgamation of two
   * interfaces, the FileSelector and the Paramterizable interface. Note that
   * you will almost certainly want the default behaviour for handling
   * Parameters, so you probably want to use the BaseExtendSelector class
   * as the base class for your dynamic selector rather than implementing
   * this interface from scratch.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public interface ExtendFileSelector extends FileSelector, Parameterizable {
  
    // No further methods necessary. This is just an amalgamation of two other
    // interfaces.
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/ExtendSelector.java
  
  Index: ExtendSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.Vector;
  
  import org.apache.tools.ant.BuildException;
  import org.apache.tools.ant.types.DataType;
  import org.apache.tools.ant.types.Path;
  import org.apache.tools.ant.types.Parameter;
  import org.apache.tools.ant.types.Reference;
  
  /**
   * Selector that selects files by forwarding the request on to other classes.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class ExtendSelector extends BaseSelector {
  
      private String classname = null;
      private ExtendFileSelector dynselector = null;
      private Vector paramVec = new Vector();
      private Path classpath = null;
  
      /**
       * Default constructor.
       */
      public ExtendSelector() {
      }
  
      /**
       * Sets the classname of the dynamic selector.
       *
       * @param classname is the class which implements this selector
       */
      public void setClassname(String classname) {
          this.classname = classname;
      }
  
      /**
       * Instantiates the identified dynamic selector class.
       */
      public void selectorCreate() {
          if (classname != null && classname.length() > 0) {
              try {
                  dynselector = (ExtendFileSelector)
                          Class.forName(classname).newInstance();
              }
              catch (ClassNotFoundException cnfexcept) {
                  setError("Selector " + classname +
                          " not initialized, no such class");
              }
              catch (InstantiationException iexcept) {
                  setError("Selector " + classname +
                          " not initialized, could not create class");
              }
              catch (IllegalAccessException iaexcept) {
                  setError("Selector " + classname +
                          " not initialized, class not accessible");
              }
          } else {
              setError("There is no classname specified");
          }
      }
  
      /**
       * Create new parameters to pass to dynamic selector.
       *
       * @param p The new Parameter object
       */
      public void addParam(Parameter p) {
          paramVec.addElement(p);
      }
  
  
      /**
       * Set the classpath to load the classname specified using an attribute.
       */
      public final void setClasspath(Path classpath) {
          if (isReference()) {
              throw tooManyAttributes();
          }
          if (this.classpath == null) {
              this.classpath = classpath;
          } else {
              this.classpath.append(classpath);
          }
      }
  
      /**
       * Specify the classpath to use to load the Selector (nested element).
       */
      public final Path createClasspath() {
          if (isReference()) {
              throw noChildrenAllowed();
          }
          if (this.classpath == null) {
              this.classpath = new Path(getProject());
          }
          return this.classpath.createPath();
      }
  
      /**
       * Get the classpath
       */
      public final Path getClasspath() {
          return classpath;
      }
  
      /**
       * Set the classpath to use for loading a dynamic selector by using
       * a reference.
       */
      public void setClasspathref(Reference r) {
          if (isReference()) {
              throw tooManyAttributes();
          }
          createClasspath().setRefid(r);
      }
  
      /**
       * These are errors specific to ExtendSelector only. If there are
       * errors in the dynamic selector, it should throw a BuildException
       * when isSelected() is called.
       */
      public void verifySettings() {
          if (classname == null || classname.length() < 1) {
              setError("The classname attribute is required");
          }
          else if (dynselector == null) {
              setError("Internal Error: The dynamic selector is not set");
          }
      }
  
  
      /**
       * Allows the dynamic selector to choose whether to select a file. This
       * is also where the Parameters are passed to the dynamic selector,
       * since we know we must have them all by now. And since we must know
       * both classpath and classname, creating the class is deferred to here
       * as well.
       */
      public boolean isSelected(File basedir, String filename, File file)
              throws BuildException {
          if (dynselector == null) {
              selectorCreate();
          }
          validate();
          if (paramVec.size() > 0) {
              Parameter[] paramArray = new Parameter[paramVec.size()];
              paramVec.copyInto(paramArray);
              // We know that dynselector must be non-null if no error message
              dynselector.setParameters(paramArray);
          }
          return dynselector.isSelected(basedir,filename,file);
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/FileSelector.java
  
  Index: FileSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  
  import org.apache.tools.ant.BuildException;
  
  /**
   * This is the interface to be used by all selectors.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public interface FileSelector {
  
      /**
       * Method that each selector will implement to create their
       * selection behaviour. If there is a problem with the setup
       * of a selector, it can throw a BuildException to indicate
       * the problem.
       *
       * @param basedir A java.io.File object for the base directory
       * @param filename The name of the file to check
       * @param file A File object for this filename
       * @return whether the file should be selected or not
       * @exception BuildException if the selector was not configured correctly
       */
      public boolean isSelected(File basedir, String filename, File file)
              throws BuildException;
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/FilenameSelector.java
  
  Index: FilenameSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Parameter;
  
  /**
   * Selector that filters files based on the filename.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class FilenameSelector extends BaseExtendSelector {
  
      private String pattern = null;
      private boolean casesensitive = true;
      private boolean negated = false;
      public final static String NAME_KEY = "name";
      public final static String CASE_KEY = "casesensitive";
      public final static String NEGATE_KEY = "negate";
  
      public FilenameSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer("{filenameselector name: ");
          buf.append(pattern);
          buf.append(" negate: ");
          if (negated) {
              buf.append("true");
          } else {
              buf.append("false");
          }
          buf.append(" casesensitive: ");
          if (casesensitive) {
              buf.append("true");
          } else {
              buf.append("false");
          }
          buf.append("}");
          return buf.toString();
      }
  
      /**
       * The name of the file, or the pattern for the name, that
       * should be used for selection.
       *
       * @param pattern the file pattern that any filename must match
       *                against in order to be selected.
       */
      public void setName(String pattern) {
          pattern = pattern.replace('/',File.separatorChar).replace('\\',
                  File.separatorChar);
          if (pattern.endsWith(File.separator)) {
              pattern += "**";
          }
          this.pattern = pattern;
      }
  
      /**
       * Whether to ignore case when checking filenames.
       *
       * @param casesensitive whether to pay attention to case sensitivity
       */
      public void setCasesensitive(boolean casesensitive) {
          this.casesensitive = casesensitive;
      }
  
      /**
       * You can optionally reverse the selection of this selector,
       * thereby emulating an <exclude> tag, by setting the attribute
       * negate to true. This is identical to surrounding the selector
       * with <not></not>.
       *
       * @param negated whether to negate this selection
       */
      public void setNegate(boolean negated) {
          this.negated = negated;
      }
  
      /**
       * When using this as a dynamic selector, this method will be called.
       * It translates each parameter into the appropriate setXXX() call.
       *
       * @param parameters the complete set of parameters for this selector
       */
      public void setParameters(Parameter[] parameters) {
          super.setParameters(parameters);
          if (parameters != null) {
              for (int i = 0; i < parameters.length; i++) {
                  String paramname = parameters[i].getName();
                  if (NAME_KEY.equalsIgnoreCase(paramname)) {
                      setName(parameters[i].getValue());
                  }
                  else if (CASE_KEY.equalsIgnoreCase(paramname)) {
                      setCasesensitive(Project.toBoolean(
                          parameters[i].getValue()));
                  }
                  else if (NEGATE_KEY.equalsIgnoreCase(paramname)) {
                      setNegate(Project.toBoolean(parameters[i].getValue()));
                  }
                  else {
                      setError("Invalid parameter " + paramname);
                  }
              }
          }
      }
  
      /**
       * Checks to make sure all settings are kosher. In this case, it
       * means that the name attribute has been set.
       *
       */
      public void verifySettings() {
          if (pattern == null) {
              setError("The name attribute is required");
          }
      }
  
      /**
       * The heart of the matter. This is where the selector gets to decide
       * on the inclusion of a file in a particular fileset. Most of the work
       * for this selector is offloaded into SelectorUtils, a static class
       * that provides the same services for both FilenameSelector and
       * DirectoryScanner.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object the selector can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
          validate();
  
          return SelectorUtils.matchPath(pattern,filename,
                  casesensitive);
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/MajoritySelector.java
  
  Index: MajoritySelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.Enumeration;
  
  /**
   * This selector is here just to shake up your thinking a bit. Don't get
   * too caught up in boolean, there are other ways you can evaluate a
   * collection of selectors. This one takes a vote of the selectors it
   * contains, and majority wins. You could also have an "all-but-one"
   * selector, a "weighted-average" selector, and so on. These are left
   * as exercises for the reader (as are the usecases where this would
   * be necessary).
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class MajoritySelector extends BaseSelectorContainer {
  
      private boolean allowtie = true;
  
      /**
       * Default constructor.
       */
      public MajoritySelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer();
          if (hasSelectors()) {
              buf.append("{majorityselect: ");
              buf.append(super.toString());
              buf.append("}");
          }
          return buf.toString();
      }
  
      public void setAllowtie(boolean tiebreaker) {
          allowtie = tiebreaker;
      }
  
      /**
       * Returns true (the file is selected) if most of the other selectors
       * agree. In case of a tie, go by the allowtie setting. That defaults
       * to true, meaning in case of a tie, the file is selected.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object for the filename that the selector
       * can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
          validate();
          int yesvotes = 0;
          int novotes = 0;
          Enumeration e = selectorElements();
          boolean result;
  
          while(e.hasMoreElements()) {
              result = ((FileSelector)e.nextElement()).isSelected(basedir,
                      filename,file);
              if (result) {
                  yesvotes = yesvotes + 1;
              }
              else {
                  novotes = novotes + 1;
              }
          }
          if (yesvotes > novotes)
          {
              return true;
          }
          else if (novotes > yesvotes) {
              return false;
          }
          // At this point, we know we have a tie.
          return allowtie;
      }
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/NoneSelector.java
  
  Index: NoneSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.Enumeration;
  
  /**
   * This selector has a collection of other selectors. All of those selectors
   * must refuse to select a file before the file is considered selected by
   * this selector.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class NoneSelector extends BaseSelectorContainer {
  
      /**
       * Default constructor.
       */
      public NoneSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer();
          if (hasSelectors()) {
              buf.append("{noneselect: ");
              buf.append(super.toString());
              buf.append("}");
          }
          return buf.toString();
      }
  
      /**
       * Returns true (the file is selected) only if all other selectors
       * agree that the file should not be selected.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object for the filename that the selector
       * can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
          validate();
          Enumeration e = selectorElements();
          boolean result;
  
          while(e.hasMoreElements()) {
              result = ((FileSelector)e.nextElement()).isSelected(basedir,
                      filename,file);
              if (result) {
                  return false;
              }
          }
          return true;
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/NotSelector.java
  
  Index: NotSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.Enumeration;
  
  /**
   * This selector has one other selectors whose meaning it inverts. It
   * actually relies on NoneSelector for its implementation of the
   * isSelected() method, but it adds a check to ensure there is only one
   * other selector contained within.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class NotSelector extends NoneSelector {
  
      /**
       * Default constructor.
       */
      public NotSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer();
          if (hasSelectors()) {
              buf.append("{notselect: ");
              buf.append(super.toString());
              buf.append("}");
          }
          return buf.toString();
      }
  
      /**
       * Makes sure that there is only one entry, sets an error message if
       * not.
       */
      public void verifySettings() {
          if (selectorCount() != 1) {
              setError("One and only one selector is allowed within the " +
                      "<not> tag");
          }
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/OrSelector.java
  
  Index: OrSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.Enumeration;
  
  /**
   * This selector has a collection of other selectors, any of which have to
   * select a file in order for this selector to select it.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class OrSelector extends BaseSelectorContainer {
  
      /**
       * Default constructor.
       */
      public OrSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer();
          if (hasSelectors()) {
              buf.append("{orselect: ");
              buf.append(super.toString());
              buf.append("}");
          }
          return buf.toString();
      }
  
      /**
       * Returns true (the file is selected) if any of the other selectors
       * agree that the file should be selected.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename the name of the file to check
       * @param file a java.io.File object for the filename that the selector
       * can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
          validate();
          Enumeration e = selectorElements();
          boolean result;
  
          // First, check that all elements are correctly configured
          while(e.hasMoreElements()) {
              result = ((FileSelector)e.nextElement()).isSelected(basedir,
                      filename,file);
              if (result) {
                  return true;
              }
          }
          return false;
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/PresentSelector.java
  
  Index: PresentSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.types.Mapper;
  import org.apache.tools.ant.util.IdentityMapper;
  import org.apache.tools.ant.util.FileNameMapper;
  import org.apache.tools.ant.types.EnumeratedAttribute;
  import org.apache.tools.ant.BuildException;
  
  /**
   * Selector that filters files based on whether they appear in another
   * directory tree. It can contain a mapper element, so isn't available
   * as an ExtendSelector (since those parameters can't hold other
   * elements).
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class PresentSelector extends BaseSelector {
  
      private String targetdir = null;
      private File targetbase = null;
      private Mapper mapperElement = null;
      private FileNameMapper map = null;
      private boolean destmustexist = true;
  
      public PresentSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer("{presentselector targetdir: ");
          buf.append(targetdir);
          buf.append(" present: ");
          if (destmustexist) {
              buf.append("both");
          } else {
              buf.append("srconly");
          }
          if (map != null) {
              buf.append(map.toString());
          }
          else if (mapperElement != null) {
              buf.append(mapperElement.toString());
          }
          buf.append("}");
          return buf.toString();
      }
  
      /**
       * The name of the file or directory which is checked for matching
       * files.
       *
       * @param targetdir the directory to scan looking for matching files.
       */
      public void setTargetdir(String targetdir) {
          this.targetdir = SelectorUtils.fixPath(targetdir);
          targetbase = new File(this.targetdir);
      }
  
      /**
       * Defines the FileNameMapper to use (nested mapper element).
       */
      public Mapper createMapper() throws BuildException {
          if (mapperElement != null) {
              throw new BuildException("Cannot define more than one mapper");
          }
          mapperElement = new Mapper(project);
          return mapperElement;
      }
  
  
      /**
       * This sets whether to select a file if its dest file is present.
       * It could be a <code>negate</code> boolean, but by doing things
       * this way, we get some documentation on how the system works.
       * A user looking at the documentation should clearly understand
       * that the ONLY files whose presence is being tested are those
       * that already exist in the source directory, hence the lack of
       * a <code>destonly</code> option.
       *
       * @param fp An attribute set to either <code>srconly</code or
       *           <code>both</code>.
       */
      public void setPresent(FilePresence fp) {
          if (fp.getIndex() == 0) {
              destmustexist = false;
          }
      }
  
      /**
       * Checks to make sure all settings are kosher. In this case, it
       * means that the targetdir attribute has been set and we have a mapper.
       */
      public void verifySettings() {
          if (targetdir == null) {
              setError("The targetdir attribute is required.");
          }
          if (mapperElement == null) {
              map = new IdentityMapper();
          }
          else {
              map = mapperElement.getImplementation();
          }
          if (map == null) {
              setError("Could not set <mapper> element.");
          }
      }
  
      /**
       * The heart of the matter. This is where the selector gets to decide
       * on the inclusion of a file in a particular fileset.
       *
       * @param basedir the base directory the scan is being done from
       * @param filename is the name of the file to check
       * @param file is a java.io.File object the selector can use
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
  
          // throw BuildException on error
          validate();
  
          // Get File object for the target directory
  	File target = targetbase;
  	if (target == null) {
              target = new File(basedir,targetdir);
  	}
  
          // Determine file whose existence is to be checked
          String[] destfiles = map.mapFileName(filename);
          // Sanity check
          if (destfiles.length != 1 || destfiles[0] == null) {
              throw new BuildException("Invalid destination file results for "
                  + targetdir + " with filename " + filename);
          }
          String destname = destfiles[0];
          File destfile = new File(target,destname);
          return destfile.exists() == destmustexist;
      }
  
      /**
       * Enumerated attribute with the values for indicating where a file's
       * presence is allowed and required.
       */
      public static class FilePresence extends EnumeratedAttribute {
          public String[] getValues() {
              return new String[] {"srconly", "both"};
          }
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/SelectorContainer.java
  
  Index: SelectorContainer.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import org.apache.tools.ant.Project;
  import org.apache.tools.ant.BuildException;
  import  org.apache.tools.ant.types.Reference;
  
  import java.io.File;
  import java.util.Enumeration;
  import java.util.Stack;
  import java.util.Vector;
  
  /**
   * This is the base class for selectors that can contain other selectors.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public interface SelectorContainer {
  
      /**
       * Indicates whether there are any selectors here.
       *
       * @return whether any selectors are in this container
       */
      public boolean hasSelectors();
  
      /**
       * Gives the count of the number of selectors in this container
       *
       * @return the number of selectors in this container
       */
      public int selectorCount();
  
      /**
       * Returns the set of selectors as an array.
       *
       * @return an array of selectors in this container
       */
      public FileSelector[] getSelectors(Project p);
  
      /**
       * Returns an enumerator for accessing the set of selectors.
       *
       * @return an enumerator that goes through each of the selectors
       */
      public Enumeration selectorElements();
  
      /**
       * Add a new selector into this container.
       *
       * @param selector the new selector to add
       * @return the selector that was added
       */
      public void appendSelector(FileSelector selector);
  
      /* Methods below all implement the static selectors */
  
      /**
       * add an "And" selector entry on the selector list
       */
      public void addAnd(AndSelector selector);
  
      /**
       * add an "Or" selector entry on the selector list
       */
      public void addOr(OrSelector selector);
  
      /**
       * add a "Not" selector entry on the selector list
       */
      public void addNot(NotSelector selector);
  
      /**
       * add a "None" selector entry on the selector list
       */
      public void addNone(NoneSelector selector);
  
      /**
       * add a majority selector entry on the selector list
       */
      public void addMajority(MajoritySelector selector);
  
      /**
       * add a selector date entry on the selector list
       */
      public void addDateselect(DateSelector selector);
  
      /**
       * add a selector size entry on the selector list
       */
      public void addSizeselect(SizeSelector selector);
  
      /**
       * add a selector filename entry on the selector list
       */
      public void addFilenameselect(FilenameSelector selector);
  
      /**
       * add an extended selector entry on the selector list
       */
      public void addExtendSelect(ExtendSelector selector);
  
      /**
       * add a contains selector entry on the selector list
       */
      public void addContainsSelect(ContainsSelector selector);
  
      /**
       * add a present selector entry on the selector list
       */
      public void addPresentSelect(PresentSelector selector);
  
      /**
       * add a depth selector entry on the selector list
       */
      public void addDepthSelect(DepthSelector selector);
  
      /**
       * add a depends selector entry on the selector list
       */
      public void addDependSelect(DependSelector selector);
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/SelectorScanner.java
  
  Index: SelectorScanner.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  package org.apache.tools.ant.types.selectors;
  
  /**
   * An interface used to describe the actions required by any type of
   * directory scanner that supports Selecters.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public interface SelectorScanner {
      /**
       * Sets the selectors the scanner should use.
       *
       * @param selectors the list of selectors
       */
      void setSelectors(FileSelector[] selectors);
  
      /**
       * Directories which were selected out of a scan.
       *
       * @param selectors list selector objects
       */
      public String[] getDeselectedDirectories();
  
      /**
       * Files which were selected out of a scan.
       *
       * @param selectors list selector objects
       */
      public String[] getDeselectedFiles();
  
  
  }
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/SelectorUtils.java
  
  Index: SelectorUtils.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  import java.util.StringTokenizer;
  import java.util.Vector;
  
  import org.apache.tools.ant.BuildException;
  
  /**
   * <p>This is a utility class used by selectors and DirectoryScanner. The
   * functionality more properly belongs just to selectors, but unfortunately
   * DirectoryScanner exposed these as protected methods. Thus we have to
   * support any subclasses of DirectoryScanner that may access these methods.
   * </p>
   * <p>This is a Singleton.</p>
   *
   * @author Arnout J. Kuiper
   * <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
   * @author <a href="mailto:umagesh@rediffmail.com">Magesh Umasankar</a>
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public final class SelectorUtils {
  
      private static SelectorUtils instance = new SelectorUtils();
  
      /**
       * Private Constructor
       */
      private SelectorUtils() {
      }
  
       /**
        * Retrieves the instance of the Singleton.
        */
      public static SelectorUtils getInstance() {
          return instance;
      }
  
      /**
       * Tests whether or not a given path matches the start of a given
       * pattern up to the first "**".
       * <p>
       * This is not a general purpose test and should only be used if you
       * can live with false positives. For example, <code>pattern=**\a</code>
       * and <code>str=b</code> will yield <code>true</code>.
       *
       * @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
       *                <code>null</code>.
       *
       * @return whether or not a given path matches the start of a given
       * pattern up to the first "**".
       */
      public static boolean matchPatternStart(String pattern, String str) {
          return matchPatternStart(pattern, str, true);
      }
      /**
       * Tests whether or not a given path matches the start of a given
       * pattern up to the first "**".
       * <p>
       * This is not a general purpose test and should only be used if you
       * can live with false positives. For example, <code>pattern=**\a</code>
       * and <code>str=b</code> will yield <code>true</code>.
       *
       * @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
       *                <code>null</code>.
       * @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 "**".
       */
      public static boolean matchPatternStart(String pattern, String str,
                                                 boolean isCaseSensitive) {
          // When str starts with a File.separator, pattern has to start with a
          // File.separator.
          // When pattern starts with a File.separator, str has to start with a
          // File.separator.
          if (str.startsWith(File.separator) !=
              pattern.startsWith(File.separator)) {
              return false;
          }
  
          Vector patDirs = tokenizePath (pattern);
          Vector strDirs = tokenizePath (str);
  
          int patIdxStart = 0;
          int patIdxEnd   = patDirs.size()-1;
          int strIdxStart = 0;
          int strIdxEnd   = strDirs.size()-1;
  
          // up to first '**'
          while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
              String patDir = (String)patDirs.elementAt(patIdxStart);
              if (patDir.equals("**")) {
                  break;
              }
              if (!match(patDir,(String)strDirs.elementAt(strIdxStart),
                      isCaseSensitive)) {
                  return false;
              }
              patIdxStart++;
              strIdxStart++;
          }
  
          if (strIdxStart > strIdxEnd) {
              // String is exhausted
              return true;
          } else if (patIdxStart > patIdxEnd) {
              // String not exhausted, but pattern is. Failure.
              return false;
          } else {
              // pattern now holds ** while string is not exhausted
              // this will generate false positives but we can live with that.
              return true;
          }
      }
  
      /**
       * Tests whether or not a given path matches a given pattern.
       *
       * @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
       *                <code>null</code>.
       *
       * @return <code>true</code> if the pattern matches against the string,
       *         or <code>false</code> otherwise.
       */
      public static boolean matchPath(String pattern, String str) {
          return matchPath(pattern, str, true);
      }
  
      /**
       * Tests whether or not a given path matches a given pattern.
       *
       * @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
       *                <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 static boolean matchPath(String pattern, String str,
              boolean isCaseSensitive) {
          // When str starts with a File.separator, pattern has to start with a
          // File.separator.
          // When pattern starts with a File.separator, str has to start with a
          // File.separator.
          if (str.startsWith(File.separator) !=
              pattern.startsWith(File.separator)) {
              return false;
          }
  
          Vector patDirs = tokenizePath (pattern);
          Vector strDirs = tokenizePath (str);
  
          int patIdxStart = 0;
          int patIdxEnd   = patDirs.size()-1;
          int strIdxStart = 0;
          int strIdxEnd   = strDirs.size()-1;
  
          // up to first '**'
          while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
              String patDir = (String)patDirs.elementAt(patIdxStart);
              if (patDir.equals("**")) {
                  break;
              }
              if (!match(patDir,(String)strDirs.elementAt(strIdxStart),
                      isCaseSensitive)) {
                  return false;
              }
              patIdxStart++;
              strIdxStart++;
          }
          if (strIdxStart > strIdxEnd) {
              // String is exhausted
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (!patDirs.elementAt(i).equals("**")) {
                      return false;
                  }
              }
              return true;
          } else {
              if (patIdxStart > patIdxEnd) {
                  // String not exhausted, but pattern is. Failure.
                  return false;
              }
          }
  
          // up to last '**'
          while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
              String patDir = (String)patDirs.elementAt(patIdxEnd);
              if (patDir.equals("**")) {
                  break;
              }
              if (!match(patDir,(String)strDirs.elementAt(strIdxEnd),
                      isCaseSensitive)) {
                  return false;
              }
              patIdxEnd--;
              strIdxEnd--;
          }
          if (strIdxStart > strIdxEnd) {
              // String is exhausted
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (!patDirs.elementAt(i).equals("**")) {
                      return false;
                  }
              }
              return true;
          }
  
          while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
              int patIdxTmp = -1;
              for (int i = patIdxStart+1; i <= patIdxEnd; i++) {
                  if (patDirs.elementAt(i).equals("**")) {
                      patIdxTmp = i;
                      break;
                  }
              }
              if (patIdxTmp == patIdxStart+1) {
                  // '**/**' situation, so skip one
                  patIdxStart++;
                  continue;
              }
              // Find the pattern between padIdxStart & padIdxTmp in str between
              // strIdxStart & strIdxEnd
              int patLength = (patIdxTmp-patIdxStart-1);
              int strLength = (strIdxEnd-strIdxStart+1);
              int foundIdx  = -1;
  strLoop:
              for (int i = 0; i <= strLength - patLength; i++) {
                  for (int j = 0; j < patLength; j++) {
                      String subPat = (String)patDirs.elementAt(patIdxStart+j+1);
                      String subStr = (String)strDirs.elementAt(strIdxStart+i+j);
                      if (!match(subPat,subStr, isCaseSensitive)) {
                          continue strLoop;
                      }
                  }
  
                  foundIdx = strIdxStart+i;
                  break;
              }
  
              if (foundIdx == -1) {
                  return false;
              }
  
              patIdxStart = patIdxTmp;
              strIdxStart = foundIdx+patLength;
          }
  
          for (int i = patIdxStart; i <= patIdxEnd; i++) {
              if (!patDirs.elementAt(i).equals("**")) {
                  return false;
              }
          }
  
          return true;
      }
  
      /**
       * Tests whether or not a string matches against a pattern.
       * The pattern may contain two special characters:<br>
       * '*' means zero or more characters<br>
       * '?' means one and only one character
       *
       * @param pattern The pattern to match against.
       *                Must not be <code>null</code>.
       * @param str     The string which must be matched against the pattern.
       *                Must not be <code>null</code>.
       *
       * @return <code>true</code> if the string matches against the pattern,
       *         or <code>false</code> otherwise.
       */
      public static boolean match(String pattern, String str) {
          return match(pattern, str, true);
      }
  
      /**
       * Tests whether or not a string matches against a pattern.
       * The pattern may contain two special characters:<br>
       * '*' means zero or more characters<br>
       * '?' means one and only one character
       *
       * @param pattern The pattern to match against.
       *                Must not be <code>null</code>.
       * @param str     The string which must be matched against the pattern.
       *                Must not be <code>null</code>.
       * @param isCaseSensitive Whether or not matching should be performed
       *                        case sensitively.
       *
       *
       * @return <code>true</code> if the string matches against the pattern,
       *         or <code>false</code> otherwise.
       */
      public static boolean match(String pattern, String str,
              boolean isCaseSensitive) {
          char[] patArr = pattern.toCharArray();
          char[] strArr = str.toCharArray();
          int patIdxStart = 0;
          int patIdxEnd   = patArr.length-1;
          int strIdxStart = 0;
          int strIdxEnd   = strArr.length-1;
          char ch;
  
          boolean containsStar = false;
          for (int i = 0; i < patArr.length; i++) {
              if (patArr[i] == '*') {
                  containsStar = true;
                  break;
              }
          }
  
          if (!containsStar) {
              // No '*'s, so we make a shortcut
              if (patIdxEnd != strIdxEnd) {
                  return false; // Pattern and string do not have the same size
              }
              for (int i = 0; i <= patIdxEnd; i++) {
                  ch = patArr[i];
                  if (ch != '?') {
                      if (isCaseSensitive && ch != strArr[i]) {
                          return false;// Character mismatch
                      }
                      if (!isCaseSensitive && Character.toUpperCase(ch) !=
                          Character.toUpperCase(strArr[i])) {
                          return false; // Character mismatch
                      }
                  }
              }
              return true; // String matches against pattern
          }
  
          if (patIdxEnd == 0) {
              return true; // Pattern contains only '*', which matches anything
          }
  
          // Process characters before first star
          while((ch = patArr[patIdxStart]) != '*' && strIdxStart <= strIdxEnd) {
              if (ch != '?') {
                  if (isCaseSensitive && ch != strArr[strIdxStart]) {
                      return false;// Character mismatch
                  }
                  if (!isCaseSensitive && Character.toUpperCase(ch) !=
                      Character.toUpperCase(strArr[strIdxStart])) {
                      return false;// Character mismatch
                  }
              }
              patIdxStart++;
              strIdxStart++;
          }
          if (strIdxStart > strIdxEnd) {
              // All characters in the string are used. Check if only '*'s are
              // left in the pattern. If so, we succeeded. Otherwise failure.
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (patArr[i] != '*') {
                      return false;
                  }
              }
              return true;
          }
  
          // Process characters after last star
          while((ch = patArr[patIdxEnd]) != '*' && strIdxStart <= strIdxEnd) {
              if (ch != '?') {
                  if (isCaseSensitive && ch != strArr[strIdxEnd]) {
                      return false;// Character mismatch
                  }
                  if (!isCaseSensitive && Character.toUpperCase(ch) !=
                      Character.toUpperCase(strArr[strIdxEnd])) {
                      return false;// Character mismatch
                  }
              }
              patIdxEnd--;
              strIdxEnd--;
          }
          if (strIdxStart > strIdxEnd) {
              // All characters in the string are used. Check if only '*'s are
              // left in the pattern. If so, we succeeded. Otherwise failure.
              for (int i = patIdxStart; i <= patIdxEnd; i++) {
                  if (patArr[i] != '*') {
                      return false;
                  }
              }
              return true;
          }
  
          // process pattern between stars. padIdxStart and patIdxEnd point
          // always to a '*'.
          while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
              int patIdxTmp = -1;
              for (int i = patIdxStart+1; i <= patIdxEnd; i++) {
                  if (patArr[i] == '*') {
                      patIdxTmp = i;
                      break;
                  }
              }
              if (patIdxTmp == patIdxStart+1) {
                  // Two stars next to each other, skip the first one.
                  patIdxStart++;
                  continue;
              }
              // Find the pattern between padIdxStart & padIdxTmp in str between
              // strIdxStart & strIdxEnd
              int patLength = (patIdxTmp-patIdxStart-1);
              int strLength = (strIdxEnd-strIdxStart+1);
              int foundIdx  = -1;
              strLoop:
              for (int i = 0; i <= strLength - patLength; i++) {
                  for (int j = 0; j < patLength; j++) {
                      ch = patArr[patIdxStart+j+1];
                      if (ch != '?') {
                          if (isCaseSensitive && ch != strArr[strIdxStart+i+j]) {
                              continue strLoop;
                          }
                          if (!isCaseSensitive && Character.toUpperCase(ch) !=
                              Character.toUpperCase(strArr[strIdxStart+i+j])) {
                              continue strLoop;
                          }
                      }
                  }
  
                  foundIdx = strIdxStart+i;
                  break;
              }
  
              if (foundIdx == -1) {
                  return false;
              }
  
              patIdxStart = patIdxTmp;
              strIdxStart = foundIdx+patLength;
          }
  
          // All characters in the string are used. Check if only '*'s are left
          // in the pattern. If so, we succeeded. Otherwise failure.
          for (int i = patIdxStart; i <= patIdxEnd; i++) {
              if (patArr[i] != '*') {
                  return false;
              }
          }
          return true;
      }
  
      /**
       * Breaks a path up into a Vector of path elements, tokenizing on
       * <code>File.separator</code>.
       *
       * @param path Path to tokenize. Must not be <code>null</code>.
       *
       * @return a Vector of path elements from the tokenized path
       */
      public static Vector tokenizePath (String path) {
          Vector ret = new Vector();
          StringTokenizer st = new StringTokenizer(path,File.separator);
          while (st.hasMoreTokens()) {
              ret.addElement(st.nextToken());
          }
          return ret;
      }
  
      /**
       * Helper method which corrects paths to use forward slashes.
       *
       * @param pattern the path pattern which needs correcting
       * @return corrected pattern
       */
      public static String fixPath(String pattern) {
          return pattern.replace('/',File.separatorChar).replace('\\',
                  File.separatorChar);
      }
  
      /**
       * Returns dependency information on these two files. If src has been
       * modified later than target, it returns true. If target doesn't exist,
       * it likewise returns true. Otherwise, target is newer than src and
       * is not out of date, thus the method returns false. It also returns
       * false if the src file doesn't even exist, since how could the
       * target then be out of date.
       *
       * @param src the original file
       * @param target the file being compared against
       * @param granularity the amount in seconds of slack we will give in
       *        determining out of dateness
       * @return whether the target is out of date
       */
      public static boolean isOutOfDate(File src, File target, int granularity) {
          if (!src.exists()) {
              return false;
          }
          if (!target.exists()) {
              return true;
          }
          if ((src.lastModified() - granularity) > target.lastModified()) {
              return true;
          }
          return false;
      }
  
  }
  
  
  
  
  1.1                  jakarta-ant/src/main/org/apache/tools/ant/types/selectors/SizeSelector.java
  
  Index: SizeSelector.java
  ===================================================================
  /*
   * The Apache Software License, Version 1.1
   *
   * Copyright (c) 2002 The Apache Software Foundation.  All rights
   * reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. The end-user documentation included with the redistribution, if
   *    any, must include the following acknowlegement:
   *       "This product includes software developed by the
   *        Apache Software Foundation (http://www.apache.org/)."
   *    Alternately, this acknowlegement may appear in the software itself,
   *    if and wherever such third-party acknowlegements normally appear.
   *
   * 4. The names "The Jakarta Project", "Ant", and "Apache Software
   *    Foundation" must not be used to endorse or promote products derived
   *    from this software without prior written permission. For written
   *    permission, please contact apache@apache.org.
   *
   * 5. Products derived from this software may not be called "Apache"
   *    nor may "Apache" appear in their names without prior written
   *    permission of the Apache Group.
   *
   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
   * SUCH DAMAGE.
   * ====================================================================
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Apache Software Foundation.  For more
   * information on the Apache Software Foundation, please see
   * <http://www.apache.org/>.
   */
  
  package org.apache.tools.ant.types.selectors;
  
  import java.io.File;
  
  import org.apache.tools.ant.types.EnumeratedAttribute;
  import org.apache.tools.ant.types.Parameter;
  import org.apache.tools.ant.BuildException;
  
  /**
   * Selector that filters files based on their size.
   *
   * @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
   * @since 1.5
   */
  public class SizeSelector extends BaseExtendSelector {
  
      private long size = -1;
      private long multiplier = 1;
      private long sizelimit = -1;
      private int cmp = 0;
      public final static String SIZE_KEY = "millis";
      public final static String UNITS_KEY = "datetime";
      public final static String WHEN_KEY = "when";
  
      public SizeSelector() {
      }
  
      public String toString() {
          StringBuffer buf = new StringBuffer("{sizeselector size: ");
          buf.append(sizelimit);
          buf.append("compare: ");
          if (cmp == 0) {
              buf.append("less");
          }
          else if (cmp == 1) {
              buf.append("more");
          } else {
              buf.append("equal");
          }
          buf.append("}");
          return buf.toString();
      }
  
      /**
       * A size selector needs to know what size to base its selecting on.
       * This will be further modified by the multiplier to get an
       * actual size limit.
       *
       * @param size the size to select against expressed in units
       */
      public void setSize(long size) {
          this.size = size;
          if ((multiplier != 0) && (size > -1)) {
              sizelimit = size * multiplier;
          }
      }
  
      /**
       * Sets the units to use for the comparison. This is a little
       * complicated because common usage has created standards that
       * play havoc with capitalization rules. Thus, some people will
       * use "K" for indicating 1000's, when the SI standard calls for
       * "k". Others have tried to introduce "K" as a multiple of 1024,
       * but that falls down when you reach "M", since "m" is already
       * defined as 0.001.
       * <p>
       * To get around this complexity, a number of standards bodies
       * have proposed the 2^10 standard, and at least one has adopted
       * it. But we are still left with a populace that isn't clear on
       * how capitalization should work.
       * <p>
       * We therefore ignore capitalization as much as possible.
       * Completely mixed case is not possible, but all upper and lower
       * forms are accepted for all long and short forms. Since we have
       * no need to work with the 0.001 case, this practice works here.
       * <p>
       * This function translates all the long and short forms that a
       * unit prefix can occur in and translates them into a single
       * multiplier.
       *
       * @param units The units to compare the size to, using an
       *        EnumeratedAttribute
       */
      public void setUnits(ByteUnits units) {
          int i = units.getIndex();
          multiplier = 0;
          if ((i > -1) && (i < 4)) {
              multiplier = 1000;
          }
          else if ((i > 3) && (i < 9)) {
              multiplier = 1024;
          }
          else if ((i > 8) && (i < 13)) {
              multiplier = 1000000;
          }
          else if ((i > 12) && (i < 18)) {
              multiplier = 1048576;
          }
          else if ((i > 17) && (i < 22)) {
              multiplier = 1000000000L;
          }
          else if ((i > 21) && (i < 27)) {
              multiplier = 1073741824L;
          }
          else if ((i > 26) && (i < 31)) {
              multiplier = 1000000000000L;
          }
          else if ((i > 30) && (i < 36)) {
              multiplier = 1099511627776L;
          }
          if ((multiplier > 0) && (size > -1)) {
              sizelimit = size * multiplier;
          }
      }
  
      /**
       * This specifies when the file should be selected, whether it be
       * when the file matches a particular size, when it is smaller,
       * or whether it is larger.
       *
       * @param cmp The comparison to perform, an EnumeratedAttribute
       */
      public void setWhen(SizeComparisons cmp) {
          this.cmp = cmp.getIndex();
      }
  
      /**
       * When using this as a dynamic selector, this method will be called.
       * It translates each parameter into the appropriate setXXX() call.
       *
       * @param parameters the complete set of parameters for this selector
       */
      public void setParameters(Parameter[] parameters) {
          super.setParameters(parameters);
          if (parameters != null) {
              for (int i = 0; i < parameters.length; i++) {
                  String paramname = parameters[i].getName();
                  if (SIZE_KEY.equalsIgnoreCase(paramname)) {
                      try {
                          setSize(new Long(parameters[i].getValue()
                                  ).longValue());
                      } catch (NumberFormatException nfe) {
                          setError("Invalid size setting "
                              + parameters[i].getValue());
                      }
                  }
                  else if (UNITS_KEY.equalsIgnoreCase(paramname)) {
                      ByteUnits units = new ByteUnits();
                      units.setValue(parameters[i].getValue());
                      setUnits(units);
                  }
                  else if (WHEN_KEY.equalsIgnoreCase(paramname)) {
                      SizeComparisons cmp = new SizeComparisons();
                      cmp.setValue(parameters[i].getValue());
                      setWhen(cmp);
                  }
                  else {
                      setError("Invalid parameter " + paramname);
                  }
              }
          }
      }
  
      /**
       * <p>Checks to make sure all settings are kosher. In this case, it
       * means that the size attribute has been set (to a positive value),
       * that the multiplier has a valid setting, and that the size limit
       * is valid. Since the latter is a calculated value, this can only
       * fail due to a programming error.
       * </p>
       * <p>If a problem is detected, the setError() method is called.
       * </p>
       */
      public void verifySettings() {
          if (size < 0) {
              setError("The size attribute is required, and must be positive");
          }
          else if (multiplier < 1) {
              setError("Invalid Units supplied, must be K,Ki,M,Mi,G,Gi,T,or Ti");
          }
          else if (sizelimit < 0) {
              setError("Internal error: Code is not setting sizelimit correctly");
          }
      }
  
      /**
       * The heart of the matter. This is where the selector gets to decide
       * on the inclusion of a file in a particular fileset.
       *
       * @param basedir A java.io.File object for the base directory
       * @param filename The name of the file to check
       * @param file A File object for this filename
       * @return whether the file should be selected or not
       */
      public boolean isSelected(File basedir, String filename, File file) {
  
          // throw BuildException on error
          validate();
  
          // Directory size never selected for
          if (file.isDirectory()) {
              return true;
          }
          if (cmp == 0) {
              return (file.length() < sizelimit);
          }
          else if (cmp == 1) {
              return (file.length() > sizelimit);
          }
          else {
              return (file.length() == sizelimit);
          }
      }
  
  
  
      /**
       * Enumerated attribute with the values for units.
       * <p>
       * This treats the standard SI units as representing powers of ten,
       * as they should. If you want the powers of 2 that approximate
       * the SI units, use the first two characters followed by a
       * <code>bi</code>. So 1024 (2^10) becomes <code>kibi</code>,
       * 1048576 (2^20) becomes <code>mebi</code>, 1073741824 (2^30)
       * becomes <code>gibi</code>, and so on. The symbols are also
       * accepted, and these are the first letter capitalized followed
       * by an <code>i</code>. <code>Ki</code>, <code>Mi</code>,
       * <code>Gi</code>, and so on. Capitalization variations on these
       * are also accepted.
       * <p>
       * This binary prefix system is approved by the IEC and appears on
       * its way for approval by other agencies, but it is not an SI
       * standard. It disambiguates things for us, though.
       */
      public static class ByteUnits extends EnumeratedAttribute {
          public String[] getValues() {
              return new String[] {"K", "k", "kilo", "KILO",
                                   "Ki", "KI", "ki", "kibi", "KIBI",
                                   "M", "m", "mega", "MEGA",
                                   "Mi", "MI", "mi", "mebi", "MEBI",
                                   "G", "g", "giga", "GIGA",
                                   "Gi", "GI", "gi", "gibi", "GIBI",
                                   "T", "t", "tera", "TERA",
              /* You wish! */      "Ti", "TI", "ti", "tebi", "TEBI"
                                   };
          }
      }
  
      /**
       * Enumerated attribute with the values for size comparison.
       */
      public static class SizeComparisons extends EnumeratedAttribute {
          public String[] getValues() {
              return new String[] {"less", "more", "equal"};
          }
      }
  
  }
  
  
  
  

--
To unsubscribe, e-mail:   <mailto:ant-dev-unsubscribe@jakarta.apache.org>
For additional commands, e-mail: <mailto:ant-dev-help@jakarta.apache.org>


Mime
View raw message