FileDocCategorySizeDatePackage
SelectorUtils.javaAPI DocApache Ant 1.7024670Wed Dec 13 06:16:20 GMT 2006org.apache.tools.ant.types.selectors

SelectorUtils

public final class SelectorUtils extends Object

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.

This is a Singleton.

since
1.5

Fields Summary
private static SelectorUtils
instance
private static final org.apache.tools.ant.util.FileUtils
FILE_UTILS
Constructors Summary
private SelectorUtils()
Private Constructor


           
      
    
Methods Summary
public static org.apache.tools.ant.types.selectors.SelectorUtilsgetInstance()
Retrieves the instance of the Singleton.

return
singleton instance

        return instance;
    
public static booleanhasWildcards(java.lang.String input)
Tests if a string contains stars or question marks

param
input a String which one wants to test for containing wildcard
return
true if the string contains at least a star or a question mark

        return (input.indexOf('*") != -1 || input.indexOf('?") != -1);
    
public static booleanisOutOfDate(java.io.File src, java.io.File target, int granularity)
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

        if (!src.exists()) {
            return false;
        }
        if (!target.exists()) {
            return true;
        }
        if ((src.lastModified() - granularity) > target.lastModified()) {
            return true;
        }
        return false;
    
public static booleanisOutOfDate(org.apache.tools.ant.types.Resource src, org.apache.tools.ant.types.Resource target, int granularity)
Returns dependency information on these two resources. 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 resource
param
target the resource being compared against
param
granularity the int amount in seconds of slack we will give in determining out of dateness
return
whether the target is out of date

        return isOutOfDate(src, target, (long) granularity);
    
public static booleanisOutOfDate(org.apache.tools.ant.types.Resource src, org.apache.tools.ant.types.Resource target, long granularity)
Returns dependency information on these two resources. 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 resource
param
target the resource being compared against
param
granularity the long amount in seconds of slack we will give in determining out of dateness
return
whether the target is out of date

        if (!src.isExists()) {
            return false;
        }
        if (!target.isExists()) {
            return true;
        }
        if ((src.getLastModified() - granularity) > target.getLastModified()) {
            return true;
        }
        return false;
    
public static booleanmatch(java.lang.String pattern, java.lang.String str)
Tests whether or not a string matches against a pattern. The pattern may contain two special characters:
'*' means zero or more characters
'?' means one and only one character

param
pattern The pattern to match against. Must not be null.
param
str The string which must be matched against the pattern. Must not be null.
return
true if the string matches against the pattern, or false otherwise.

        return match(pattern, str, true);
    
public static booleanmatch(java.lang.String pattern, java.lang.String str, boolean isCaseSensitive)
Tests whether or not a string matches against a pattern. The pattern may contain two special characters:
'*' means zero or more characters
'?' means one and only one character

param
pattern The pattern to match against. Must not be null.
param
str The string which must be matched against the pattern. Must not be null.
param
isCaseSensitive Whether or not matching should be performed case sensitively.
return
true if the string matches against the pattern, or false otherwise.

        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;
    
public static booleanmatchPath(java.lang.String pattern, java.lang.String str)
Tests whether or not a given path matches a given pattern.

param
pattern The pattern to match against. Must not be null.
param
str The path to match, as a String. Must not be null.
return
true if the pattern matches against the string, or false otherwise.

        return matchPath(pattern, str, true);
    
public static booleanmatchPath(java.lang.String pattern, java.lang.String str, boolean isCaseSensitive)
Tests whether or not a given path matches a given pattern.

param
pattern The pattern to match against. Must not be null.
param
str The path to match, as a String. Must not be null.
param
isCaseSensitive Whether or not matching should be performed case sensitively.
return
true if the pattern matches against the string, or false otherwise.

        String[] patDirs = tokenizePathAsArray(pattern);
        String[] strDirs = tokenizePathAsArray(str);

        int patIdxStart = 0;
        int patIdxEnd = patDirs.length - 1;
        int strIdxStart = 0;
        int strIdxEnd = strDirs.length - 1;

        // up to first '**'
        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
            String patDir = patDirs[patIdxStart];
            if (patDir.equals("**")) {
                break;
            }
            if (!match(patDir, strDirs[strIdxStart], isCaseSensitive)) {
                patDirs = null;
                strDirs = null;
                return false;
            }
            patIdxStart++;
            strIdxStart++;
        }
        if (strIdxStart > strIdxEnd) {
            // String is exhausted
            for (int i = patIdxStart; i <= patIdxEnd; i++) {
                if (!patDirs[i].equals("**")) {
                    patDirs = null;
                    strDirs = null;
                    return false;
                }
            }
            return true;
        } else {
            if (patIdxStart > patIdxEnd) {
                // String not exhausted, but pattern is. Failure.
                patDirs = null;
                strDirs = null;
                return false;
            }
        }

        // up to last '**'
        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
            String patDir = patDirs[patIdxEnd];
            if (patDir.equals("**")) {
                break;
            }
            if (!match(patDir, strDirs[strIdxEnd], isCaseSensitive)) {
                patDirs = null;
                strDirs = null;
                return false;
            }
            patIdxEnd--;
            strIdxEnd--;
        }
        if (strIdxStart > strIdxEnd) {
            // String is exhausted
            for (int i = patIdxStart; i <= patIdxEnd; i++) {
                if (!patDirs[i].equals("**")) {
                    patDirs = null;
                    strDirs = null;
                    return false;
                }
            }
            return true;
        }

        while (patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd) {
            int patIdxTmp = -1;
            for (int i = patIdxStart + 1; i <= patIdxEnd; i++) {
                if (patDirs[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 = patDirs[patIdxStart + j + 1];
                                String subStr = strDirs[strIdxStart + i + j];
                                if (!match(subPat, subStr, isCaseSensitive)) {
                                    continue strLoop;
                                }
                            }

                            foundIdx = strIdxStart + i;
                            break;
                        }

            if (foundIdx == -1) {
                patDirs = null;
                strDirs = null;
                return false;
            }

            patIdxStart = patIdxTmp;
            strIdxStart = foundIdx + patLength;
        }

        for (int i = patIdxStart; i <= patIdxEnd; i++) {
            if (!patDirs[i].equals("**")) {
                patDirs = null;
                strDirs = null;
                return false;
            }
        }

        return true;
    
public static booleanmatchPatternStart(java.lang.String pattern, java.lang.String str)
Tests whether or not a given path matches the start of a given pattern up to the first "**".

This is not a general purpose test and should only be used if you can live with false positives. For example, pattern=**\a and str=b will yield true.

param
pattern The pattern to match against. Must not be null.
param
str The path to match, as a String. Must not be null.
return
whether or not a given path matches the start of a given pattern up to the first "**".

        return matchPatternStart(pattern, str, true);
    
public static booleanmatchPatternStart(java.lang.String pattern, java.lang.String str, boolean isCaseSensitive)
Tests whether or not a given path matches the start of a given pattern up to the first "**".

This is not a general purpose test and should only be used if you can live with false positives. For example, pattern=**\a and str=b will yield true.

param
pattern The pattern to match against. Must not be null.
param
str The path to match, as a String. Must not be null.
param
isCaseSensitive Whether or not matching should be performed case sensitively.
return
whether or not a given path matches the start of a given pattern up to the first "**".

        // 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;
        }

        String[] patDirs = tokenizePathAsArray(pattern);
        String[] strDirs = tokenizePathAsArray(str);

        int patIdxStart = 0;
        int patIdxEnd = patDirs.length - 1;
        int strIdxStart = 0;
        int strIdxEnd = strDirs.length - 1;

        // up to first '**'
        while (patIdxStart <= patIdxEnd && strIdxStart <= strIdxEnd) {
            String patDir = patDirs[patIdxStart];
            if (patDir.equals("**")) {
                break;
            }
            if (!match(patDir, strDirs[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;
        }
    
public static java.lang.StringremoveWhitespace(java.lang.String input)
"Flattens" a string by removing all whitespace (space, tab, linefeed, carriage return, and formfeed). This uses StringTokenizer and the default set of tokens as documented in the single arguement constructor.

param
input a String to remove all whitespace.
return
a String that has had all whitespace removed.

        StringBuffer result = new StringBuffer();
        if (input != null) {
            StringTokenizer st = new StringTokenizer(input);
            while (st.hasMoreTokens()) {
                result.append(st.nextToken());
            }
        }
        return result.toString();
    
public static java.lang.StringrtrimWildcardTokens(java.lang.String input)
removes from a pattern all tokens to the right containing wildcards

param
input the input string
return
the leftmost part of the pattern without wildcards

        String[] tokens = tokenizePathAsArray(input);
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < tokens.length; i++) {
            if (hasWildcards(tokens[i])) {
                break;
            }
            if (i > 0 && sb.charAt(sb.length() - 1) != File.separatorChar) {
                sb.append(File.separator);
            }
            sb.append(tokens[i]);
        }
        return sb.toString();
    
public static java.util.VectortokenizePath(java.lang.String path, java.lang.String separator)
Breaks a path up into a Vector of path elements, tokenizing on

param
path Path to tokenize. Must not be null.
param
separator the separator against which to tokenize.
return
a Vector of path elements from the tokenized path
since
Ant 1.6

        Vector ret = new Vector();
        if (FileUtils.isAbsolutePath(path)) {
            String[] s = FILE_UTILS.dissect(path);
            ret.add(s[0]);
            path = s[1];
        }
        StringTokenizer st = new StringTokenizer(path, separator);
        while (st.hasMoreTokens()) {
            ret.addElement(st.nextToken());
        }
        return ret;
    
public static java.util.VectortokenizePath(java.lang.String path)
Breaks a path up into a Vector of path elements, tokenizing on File.separator.

param
path Path to tokenize. Must not be null.
return
a Vector of path elements from the tokenized path

        return tokenizePath(path, File.separator);
    
private static java.lang.String[]tokenizePathAsArray(java.lang.String path)
Same as {@link #tokenizePath tokenizePath} but hopefully faster.

        String root = null;
        if (FileUtils.isAbsolutePath(path)) {
            String[] s = FILE_UTILS.dissect(path);
            root = s[0];
            path = s[1];
        }
        char sep = File.separatorChar;
        int start = 0;
        int len = path.length();
        int count = 0;
        for (int pos = 0; pos < len; pos++) {
            if (path.charAt(pos) == sep) {
                if (pos != start) {
                    count++;
                }
                start = pos + 1;
            }
        }
        if (len != start) {
            count++;
        }
        String[] l = new String[count + ((root == null) ? 0 : 1)];

        if (root != null) {
            l[0] = root;
            count = 1;
        } else {
            count = 0;
        }
        start = 0;
        for (int pos = 0; pos < len; pos++) {
            if (path.charAt(pos) == sep) {
                if (pos != start) {
                    String tok = path.substring(start, pos);
                    l[count++] = tok;
                }
                start = pos + 1;
            }
        }
        if (len != start) {
            String tok = path.substring(start);
            l[count/*++*/] = tok;
        }
        return l;