Browse Source

Create a utility class to contain all the static scanner utility functions

git-svn-id: https://svn.apache.org/repos/asf/ant/core/trunk@270840 13f79535-47bb-0310-9956-ffa450edef68
master
Peter Donald 23 years ago
parent
commit
fef5fd66d1
12 changed files with 1090 additions and 1064 deletions
  1. +3
    -2
      proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/Expand.java
  2. +2
    -1
      proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/ide/VAJWorkspaceScanner.java
  3. +2
    -1
      proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java
  4. +6
    -516
      proposal/myrmidon/src/main/org/apache/tools/ant/types/DirectoryScanner.java
  5. +7
    -12
      proposal/myrmidon/src/main/org/apache/tools/ant/types/PatternSet.java
  6. +525
    -0
      proposal/myrmidon/src/main/org/apache/tools/ant/types/ScannerUtil.java
  7. +3
    -2
      proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/Expand.java
  8. +2
    -1
      proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/optional/ide/VAJWorkspaceScanner.java
  9. +2
    -1
      proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java
  10. +6
    -516
      proposal/myrmidon/src/todo/org/apache/tools/ant/types/DirectoryScanner.java
  11. +7
    -12
      proposal/myrmidon/src/todo/org/apache/tools/ant/types/PatternSet.java
  12. +525
    -0
      proposal/myrmidon/src/todo/org/apache/tools/ant/types/ScannerUtil.java

+ 3
- 2
proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/Expand.java View File

@@ -22,6 +22,7 @@ import org.apache.myrmidon.api.TaskException;
import org.apache.tools.ant.types.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.PatternSet;
import org.apache.tools.ant.types.ScannerUtil;

/**
* Unzip a file.
@@ -205,7 +206,7 @@ public class Expand extends MatchingTask
{
for( int w = 0; w < incls.length; w++ )
{
boolean isIncl = DirectoryScanner.match( incls[ w ], name );
boolean isIncl = ScannerUtil.match( incls[ w ], name );
if( isIncl )
{
included = true;
@@ -218,7 +219,7 @@ public class Expand extends MatchingTask
{
for( int w = 0; w < excls.length; w++ )
{
boolean isExcl = DirectoryScanner.match( excls[ w ], name );
boolean isExcl = ScannerUtil.match( excls[ w ], name );
if( isExcl )
{
included = false;


+ 2
- 1
proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/ide/VAJWorkspaceScanner.java View File

@@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.apache.tools.ant.types.DirectoryScanner;
import org.apache.tools.ant.types.ScannerUtil;

/**
* Class for scanning a Visual Age for Java workspace for packages matching a
@@ -69,7 +70,7 @@ class VAJWorkspaceScanner extends DirectoryScanner
*/
protected static boolean match( String pattern, String str )
{
return DirectoryScanner.match( pattern, str );
return ScannerUtil.match( pattern, str );
}

/**


+ 2
- 1
proposal/myrmidon/src/main/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java View File

@@ -18,6 +18,7 @@ import com.starbase.util.Platform;
import java.util.StringTokenizer;
import org.apache.myrmidon.api.TaskException;
import org.apache.tools.ant.types.DirectoryScanner;
import org.apache.tools.ant.types.ScannerUtil;

/**
* Checks out files from a specific StarTeam server, project, view, and folder.
@@ -765,7 +766,7 @@ public class AntStarTeamCheckOut extends org.apache.tools.ant.Task
StringTokenizer exStr = new StringTokenizer( patterns, " " );
while( exStr.hasMoreTokens() )
{
if( DirectoryScanner.match( exStr.nextToken(), pName ) )
if( ScannerUtil.match( exStr.nextToken(), pName ) )
{
return true;
}


+ 6
- 516
proposal/myrmidon/src/main/org/apache/tools/ant/types/DirectoryScanner.java View File

@@ -91,24 +91,6 @@ import org.apache.myrmidon.api.TaskException;
public class DirectoryScanner
implements FileScanner
{
/**
* Patterns that should be excluded by default.
*
* @see #addDefaultExcludes()
*/
private final static String[] DEFAULTEXCLUDES =
{
"**/*~",
"**/#*#",
"**/.#*",
"**/%*%",
"**/CVS",
"**/CVS/**",
"**/.cvsignore",
"**/SCCS",
"**/SCCS/**",
"**/vssver.scc"
};

/**
* Have the ArrayLists holding our results been built by a slow scan?
@@ -174,493 +156,6 @@ public class DirectoryScanner
*/
private String[] m_includes;

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
public static boolean match( final String pattern, final String str )
{
return match( pattern, str, true );
}

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @param isCaseSensitive Description of Parameter
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
protected static boolean match( final String pattern,
final String str,
final 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;
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern, final String str )
{
return matchPath( pattern, str, true );
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must a case sensitive match be done?
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxStart ), isCaseSensitive ) )
{
return false;
}
patIdxStart++;
strIdxStart++;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( 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.get( patIdxEnd );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxEnd ), isCaseSensitive ) )
{
return false;
}
patIdxEnd--;
strIdxEnd--;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( i ).equals( "**" ) )
{
return false;
}
}
return true;
}

while( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
{
int patIdxTmp = -1;
for( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
{
if( patDirs.get( 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.get( patIdxStart + j + 1 );
String subStr = (String)strDirs.get( 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.get( i ).equals( "**" ) )
{
return false;
}
}

return true;
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern, final String str )
{
return matchPatternStart( pattern, str, true );
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must matches be case sensitive?
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( 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;
}
}

/**
* Sets the basedir for scanning. This is the directory that is scanned
* recursively. All '/' and '\' characters are replaced by <code>File.separatorChar</code>
@@ -900,14 +395,14 @@ public class DirectoryScanner
{
int excludesLength = m_excludes == null ? 0 : m_excludes.length;
String[] newExcludes;
newExcludes = new String[ excludesLength + DEFAULTEXCLUDES.length ];
newExcludes = new String[ excludesLength + ScannerUtil.DEFAULTEXCLUDES.length ];
if( excludesLength > 0 )
{
System.arraycopy( m_excludes, 0, newExcludes, 0, excludesLength );
}
for( int i = 0; i < DEFAULTEXCLUDES.length; i++ )
for( int i = 0; i < ScannerUtil.DEFAULTEXCLUDES.length; i++ )
{
newExcludes[ i + excludesLength ] = DEFAULTEXCLUDES[ i ].replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
newExcludes[ i + excludesLength ] = ScannerUtil.DEFAULTEXCLUDES[ i ].replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
}
m_excludes = newExcludes;
}
@@ -982,7 +477,7 @@ public class DirectoryScanner
{
for( int i = 0; i < m_excludes.length; i++ )
{
if( matchPath( m_excludes[ i ], name, m_isCaseSensitive ) )
if( ScannerUtil.matchPath( m_excludes[ i ], name, m_isCaseSensitive ) )
{
return true;
}
@@ -1001,7 +496,7 @@ public class DirectoryScanner
{
for( int i = 0; i < m_includes.length; i++ )
{
if( matchPath( m_includes[ i ], name, m_isCaseSensitive ) )
if( ScannerUtil.matchPath( m_includes[ i ], name, m_isCaseSensitive ) )
{
return true;
}
@@ -1020,7 +515,7 @@ public class DirectoryScanner
{
for( int i = 0; i < m_includes.length; i++ )
{
if( matchPatternStart( m_includes[ i ], name, m_isCaseSensitive ) )
if( ScannerUtil.matchPatternStart( m_includes[ i ], name, m_isCaseSensitive ) )
{
return true;
}
@@ -1166,11 +661,6 @@ public class DirectoryScanner
m_haveSlowResults = true;
}

public static String[] getDEFAULTEXCLUDES()
{
return DEFAULTEXCLUDES;
}

public ArrayList getDirsExcluded()
{
return m_dirsExcluded;


+ 7
- 12
proposal/myrmidon/src/main/org/apache/tools/ant/types/PatternSet.java View File

@@ -13,23 +13,18 @@ import java.util.StringTokenizer;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.framework.Pattern;
import org.apache.tools.ant.ProjectComponent;

/**
* Named collection of include/exclude tags. <p>
*
* Moved out of MatchingTask to make it a standalone object that could be
* referenced (by scripts for example).
*
* @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
* @author Stefano Mazzocchi <a href="mailto:stefano@apache.org">
* stefano@apache.org</a>
* @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a>
* @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</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:peter@apache.org">Peter Donald</a>
*/
public class PatternSet
extends ProjectComponent
{
private ArrayList m_includeList = new ArrayList();
private ArrayList m_excludeList = new ArrayList();
@@ -106,8 +101,8 @@ public class PatternSet

public String toString()
{
return "patternSet{ includes: " + m_includeList +
" excludes: " + m_excludeList + " }";
return "PatternSet [ includes: " + m_includeList +
" excludes: " + m_excludeList + " ]";
}

private Pattern[] parsePatterns( final String patternString )


+ 525
- 0
proposal/myrmidon/src/main/org/apache/tools/ant/types/ScannerUtil.java View File

@@ -0,0 +1,525 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.tools.ant.types;

import java.io.File;
import java.util.ArrayList;
import java.util.StringTokenizer;

/**
*
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class ScannerUtil
{
/**
* Patterns that should be excluded by default.
*/
public final static String[] DEFAULTEXCLUDES = new String[]
{
"**/*~",
"**/#*#",
"**/.#*",
"**/%*%",
"**/CVS",
"**/CVS/**",
"**/.cvsignore",
"**/SCCS",
"**/SCCS/**",
"**/vssver.scc"
};

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
public static boolean match( final String pattern, final String str )
{
return match( pattern, str, true );
}

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @param isCaseSensitive Description of Parameter
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
protected static boolean match( final String pattern,
final String str,
final 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;
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern, final String str )
{
return matchPath( pattern, str, true );
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must a case sensitive match be done?
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxStart ), isCaseSensitive ) )
{
return false;
}
patIdxStart++;
strIdxStart++;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( 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.get( patIdxEnd );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxEnd ), isCaseSensitive ) )
{
return false;
}
patIdxEnd--;
strIdxEnd--;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( i ).equals( "**" ) )
{
return false;
}
}
return true;
}

while( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
{
int patIdxTmp = -1;
for( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
{
if( patDirs.get( 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.get( patIdxStart + j + 1 );
String subStr = (String)strDirs.get( 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.get( i ).equals( "**" ) )
{
return false;
}
}

return true;
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern, final String str )
{
return matchPatternStart( pattern, str, true );
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must matches be case sensitive?
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( 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;
}
}
}

+ 3
- 2
proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/Expand.java View File

@@ -22,6 +22,7 @@ import org.apache.myrmidon.api.TaskException;
import org.apache.tools.ant.types.DirectoryScanner;
import org.apache.tools.ant.types.FileSet;
import org.apache.tools.ant.types.PatternSet;
import org.apache.tools.ant.types.ScannerUtil;

/**
* Unzip a file.
@@ -205,7 +206,7 @@ public class Expand extends MatchingTask
{
for( int w = 0; w < incls.length; w++ )
{
boolean isIncl = DirectoryScanner.match( incls[ w ], name );
boolean isIncl = ScannerUtil.match( incls[ w ], name );
if( isIncl )
{
included = true;
@@ -218,7 +219,7 @@ public class Expand extends MatchingTask
{
for( int w = 0; w < excls.length; w++ )
{
boolean isExcl = DirectoryScanner.match( excls[ w ], name );
boolean isExcl = ScannerUtil.match( excls[ w ], name );
if( isExcl )
{
included = false;


+ 2
- 1
proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/optional/ide/VAJWorkspaceScanner.java View File

@@ -15,6 +15,7 @@ import java.util.ArrayList;
import java.util.Iterator;
import java.util.StringTokenizer;
import org.apache.tools.ant.types.DirectoryScanner;
import org.apache.tools.ant.types.ScannerUtil;

/**
* Class for scanning a Visual Age for Java workspace for packages matching a
@@ -69,7 +70,7 @@ class VAJWorkspaceScanner extends DirectoryScanner
*/
protected static boolean match( String pattern, String str )
{
return DirectoryScanner.match( pattern, str );
return ScannerUtil.match( pattern, str );
}

/**


+ 2
- 1
proposal/myrmidon/src/todo/org/apache/tools/ant/taskdefs/optional/scm/AntStarTeamCheckOut.java View File

@@ -18,6 +18,7 @@ import com.starbase.util.Platform;
import java.util.StringTokenizer;
import org.apache.myrmidon.api.TaskException;
import org.apache.tools.ant.types.DirectoryScanner;
import org.apache.tools.ant.types.ScannerUtil;

/**
* Checks out files from a specific StarTeam server, project, view, and folder.
@@ -765,7 +766,7 @@ public class AntStarTeamCheckOut extends org.apache.tools.ant.Task
StringTokenizer exStr = new StringTokenizer( patterns, " " );
while( exStr.hasMoreTokens() )
{
if( DirectoryScanner.match( exStr.nextToken(), pName ) )
if( ScannerUtil.match( exStr.nextToken(), pName ) )
{
return true;
}


+ 6
- 516
proposal/myrmidon/src/todo/org/apache/tools/ant/types/DirectoryScanner.java View File

@@ -91,24 +91,6 @@ import org.apache.myrmidon.api.TaskException;
public class DirectoryScanner
implements FileScanner
{
/**
* Patterns that should be excluded by default.
*
* @see #addDefaultExcludes()
*/
private final static String[] DEFAULTEXCLUDES =
{
"**/*~",
"**/#*#",
"**/.#*",
"**/%*%",
"**/CVS",
"**/CVS/**",
"**/.cvsignore",
"**/SCCS",
"**/SCCS/**",
"**/vssver.scc"
};

/**
* Have the ArrayLists holding our results been built by a slow scan?
@@ -174,493 +156,6 @@ public class DirectoryScanner
*/
private String[] m_includes;

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
public static boolean match( final String pattern, final String str )
{
return match( pattern, str, true );
}

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @param isCaseSensitive Description of Parameter
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
protected static boolean match( final String pattern,
final String str,
final 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;
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern, final String str )
{
return matchPath( pattern, str, true );
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must a case sensitive match be done?
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxStart ), isCaseSensitive ) )
{
return false;
}
patIdxStart++;
strIdxStart++;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( 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.get( patIdxEnd );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxEnd ), isCaseSensitive ) )
{
return false;
}
patIdxEnd--;
strIdxEnd--;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( i ).equals( "**" ) )
{
return false;
}
}
return true;
}

while( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
{
int patIdxTmp = -1;
for( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
{
if( patDirs.get( 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.get( patIdxStart + j + 1 );
String subStr = (String)strDirs.get( 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.get( i ).equals( "**" ) )
{
return false;
}
}

return true;
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern, final String str )
{
return matchPatternStart( pattern, str, true );
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must matches be case sensitive?
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( 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;
}
}

/**
* Sets the basedir for scanning. This is the directory that is scanned
* recursively. All '/' and '\' characters are replaced by <code>File.separatorChar</code>
@@ -900,14 +395,14 @@ public class DirectoryScanner
{
int excludesLength = m_excludes == null ? 0 : m_excludes.length;
String[] newExcludes;
newExcludes = new String[ excludesLength + DEFAULTEXCLUDES.length ];
newExcludes = new String[ excludesLength + ScannerUtil.DEFAULTEXCLUDES.length ];
if( excludesLength > 0 )
{
System.arraycopy( m_excludes, 0, newExcludes, 0, excludesLength );
}
for( int i = 0; i < DEFAULTEXCLUDES.length; i++ )
for( int i = 0; i < ScannerUtil.DEFAULTEXCLUDES.length; i++ )
{
newExcludes[ i + excludesLength ] = DEFAULTEXCLUDES[ i ].replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
newExcludes[ i + excludesLength ] = ScannerUtil.DEFAULTEXCLUDES[ i ].replace( '/', File.separatorChar ).replace( '\\', File.separatorChar );
}
m_excludes = newExcludes;
}
@@ -982,7 +477,7 @@ public class DirectoryScanner
{
for( int i = 0; i < m_excludes.length; i++ )
{
if( matchPath( m_excludes[ i ], name, m_isCaseSensitive ) )
if( ScannerUtil.matchPath( m_excludes[ i ], name, m_isCaseSensitive ) )
{
return true;
}
@@ -1001,7 +496,7 @@ public class DirectoryScanner
{
for( int i = 0; i < m_includes.length; i++ )
{
if( matchPath( m_includes[ i ], name, m_isCaseSensitive ) )
if( ScannerUtil.matchPath( m_includes[ i ], name, m_isCaseSensitive ) )
{
return true;
}
@@ -1020,7 +515,7 @@ public class DirectoryScanner
{
for( int i = 0; i < m_includes.length; i++ )
{
if( matchPatternStart( m_includes[ i ], name, m_isCaseSensitive ) )
if( ScannerUtil.matchPatternStart( m_includes[ i ], name, m_isCaseSensitive ) )
{
return true;
}
@@ -1166,11 +661,6 @@ public class DirectoryScanner
m_haveSlowResults = true;
}

public static String[] getDEFAULTEXCLUDES()
{
return DEFAULTEXCLUDES;
}

public ArrayList getDirsExcluded()
{
return m_dirsExcluded;


+ 7
- 12
proposal/myrmidon/src/todo/org/apache/tools/ant/types/PatternSet.java View File

@@ -13,23 +13,18 @@ import java.util.StringTokenizer;
import org.apache.myrmidon.api.TaskContext;
import org.apache.myrmidon.api.TaskException;
import org.apache.myrmidon.framework.Pattern;
import org.apache.tools.ant.ProjectComponent;

/**
* Named collection of include/exclude tags. <p>
*
* Moved out of MatchingTask to make it a standalone object that could be
* referenced (by scripts for example).
*
* @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
* @author Stefano Mazzocchi <a href="mailto:stefano@apache.org">
* stefano@apache.org</a>
* @author Sam Ruby <a href="mailto:rubys@us.ibm.com">rubys@us.ibm.com</a>
* @author Jon S. Stevens <a href="mailto:jon@clearink.com">jon@clearink.com</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:peter@apache.org">Peter Donald</a>
*/
public class PatternSet
extends ProjectComponent
{
private ArrayList m_includeList = new ArrayList();
private ArrayList m_excludeList = new ArrayList();
@@ -106,8 +101,8 @@ public class PatternSet

public String toString()
{
return "patternSet{ includes: " + m_includeList +
" excludes: " + m_excludeList + " }";
return "PatternSet [ includes: " + m_includeList +
" excludes: " + m_excludeList + " ]";
}

private Pattern[] parsePatterns( final String patternString )


+ 525
- 0
proposal/myrmidon/src/todo/org/apache/tools/ant/types/ScannerUtil.java View File

@@ -0,0 +1,525 @@
/*
* Copyright (C) The Apache Software Foundation. All rights reserved.
*
* This software is published under the terms of the Apache Software License
* version 1.1, a copy of which has been included with this distribution in
* the LICENSE.txt file.
*/
package org.apache.tools.ant.types;

import java.io.File;
import java.util.ArrayList;
import java.util.StringTokenizer;

/**
*
*
* @author <a href="mailto:peter@apache.org">Peter Donald</a>
* @version $Revision$ $Date$
*/
public class ScannerUtil
{
/**
* Patterns that should be excluded by default.
*/
public final static String[] DEFAULTEXCLUDES = new String[]
{
"**/*~",
"**/#*#",
"**/.#*",
"**/%*%",
"**/CVS",
"**/CVS/**",
"**/.cvsignore",
"**/SCCS",
"**/SCCS/**",
"**/vssver.scc"
};

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
public static boolean match( final String pattern, final String str )
{
return match( pattern, str, true );
}

/**
* Matches a string against a pattern. The pattern contains two special
* characters: '*' which means zero or more characters, '?' which means one
* and only one character.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string that must be matched against the pattern
* @param isCaseSensitive Description of Parameter
* @return <code>true</code> when the string matches against the pattern,
* <code>false</code> otherwise.
*/
protected static boolean match( final String pattern,
final String str,
final 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;
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern, final String str )
{
return matchPath( pattern, str, true );
}

/**
* Matches a path against a pattern.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must a case sensitive match be done?
* @return <code>true</code> when the pattern matches against the string.
* <code>false</code> otherwise.
*/
protected static boolean matchPath( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxStart ), isCaseSensitive ) )
{
return false;
}
patIdxStart++;
strIdxStart++;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( 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.get( patIdxEnd );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( strIdxEnd ), isCaseSensitive ) )
{
return false;
}
patIdxEnd--;
strIdxEnd--;
}
if( strIdxStart > strIdxEnd )
{
// String is exhausted
for( int i = patIdxStart; i <= patIdxEnd; i++ )
{
if( !patDirs.get( i ).equals( "**" ) )
{
return false;
}
}
return true;
}

while( patIdxStart != patIdxEnd && strIdxStart <= strIdxEnd )
{
int patIdxTmp = -1;
for( int i = patIdxStart + 1; i <= patIdxEnd; i++ )
{
if( patDirs.get( 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.get( patIdxStart + j + 1 );
String subStr = (String)strDirs.get( 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.get( i ).equals( "**" ) )
{
return false;
}
}

return true;
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern, final String str )
{
return matchPatternStart( pattern, str, true );
}

/**
* Does the path match the start of this 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.</p> <p>
*
* <code>pattern=**\\a</code> and <code>str=b</code> will yield true.
*
* @param pattern the (non-null) pattern to match against
* @param str the (non-null) string (path) to match
* @param isCaseSensitive must matches be case sensitive?
* @return Description of the Returned Value
*/
protected static boolean matchPatternStart( final String pattern,
final String str,
final 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;
}

ArrayList patDirs = new ArrayList();
StringTokenizer st = new StringTokenizer( pattern, File.separator );
while( st.hasMoreTokens() )
{
patDirs.add( st.nextToken() );
}

ArrayList strDirs = new ArrayList();
st = new StringTokenizer( str, File.separator );
while( st.hasMoreTokens() )
{
strDirs.add( st.nextToken() );
}

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.get( patIdxStart );
if( patDir.equals( "**" ) )
{
break;
}
if( !match( patDir, (String)strDirs.get( 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;
}
}
}

Loading…
Cancel
Save