You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by kr...@apache.org on 2012/10/01 22:01:21 UTC
svn commit: r1392561 - in /maven/shared/trunk/maven-shared-utils/src:
main/java/org/apache/maven/shared/utils/io/
test/java/org/apache/maven/shared/utils/io/
Author: krosenvold
Date: Mon Oct 1 20:01:21 2012
New Revision: 1392561
URL: http://svn.apache.org/viewvc?rev=1392561&view=rev
Log:
o Backported performance pathc from plexus.
I am the original author of this patch
Added:
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java
maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternTest.java
maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternsTest.java
Modified:
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java
maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java
Modified: maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java?rev=1392561&r1=1392560&r2=1392561&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/DirectoryScanner.java Mon Oct 1 20:01:21 2012
@@ -79,7 +79,7 @@ import java.util.Set;
* Case sensitivity may be turned off if necessary. By default, it is turned on.
* <p>
* Example of usage:
- *
+ *
* <pre>
* String[] includes = { "**\\*.class" };
* String[] excludes = { "modules\\*\\**" };
@@ -88,7 +88,7 @@ import java.util.Set;
* ds.setBasedir( new File( "test" ) );
* ds.setCaseSensitive( true );
* ds.scan();
- *
+ *
* System.out.println( "FILES:" );
* String[] files = ds.getIncludedFiles();
* for ( int i = 0; i < files.length; i++ )
@@ -96,12 +96,12 @@ import java.util.Set;
* System.out.println( files[i] );
* }
* </pre>
- *
+ *
* This will scan a directory called test for .class files, but excludes all files in all proper subdirectories of a
* directory called "modules"
* <p>
* This class must not be used from multiple Threads concurrently!
- *
+ *
* @author Arnout J. Kuiper <a href="mailto:ajkuiper@wxs.nl">ajkuiper@wxs.nl</a>
* @author Magesh Umasankar
* @author <a href="mailto:bruce@callenish.com">Bruce Atherton</a>
@@ -111,7 +111,7 @@ public class DirectoryScanner
{
/**
* Patterns which should be excluded by default.
- *
+ *
* @see #addDefaultExcludes()
*/
public static final String[] DEFAULTEXCLUDES = {
@@ -169,6 +169,11 @@ public class DirectoryScanner
/** The patterns for the files to be excluded. */
protected String[] excludes;
+ private MatchPatterns excludesPatterns;
+
+ private MatchPatterns includesPatterns;
+
+
/**
* The files which matched at least one include and no excludes and were selected.
*/
@@ -215,7 +220,7 @@ public class DirectoryScanner
/**
* Whether or not symbolic links should be followed.
- *
+ *
* @since Ant 1.5
*/
private boolean followSymlinks = true;
@@ -245,7 +250,7 @@ public class DirectoryScanner
* <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 "**".
@@ -260,7 +265,7 @@ public class DirectoryScanner
* <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.
@@ -273,7 +278,7 @@ public class DirectoryScanner
/**
* 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.
@@ -285,7 +290,7 @@ public class DirectoryScanner
/**
* 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.
@@ -300,7 +305,7 @@ public class DirectoryScanner
* 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.
@@ -314,7 +319,7 @@ public class DirectoryScanner
* 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.
@@ -329,7 +334,7 @@ public class DirectoryScanner
* 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. Must not be <code>null</code>.
*/
public void setBasedir( final String basedir )
@@ -340,7 +345,7 @@ public class DirectoryScanner
/**
* Sets the base directory to be scanned. This is the directory which is scanned recursively.
- *
+ *
* @param basedir The base directory for scanning. Should not be <code>null</code>.
*/
public void setBasedir( final File basedir )
@@ -350,7 +355,7 @@ public class DirectoryScanner
/**
* Returns the base directory to be scanned. This is the directory which is scanned recursively.
- *
+ *
* @return the base directory to be scanned
*/
public File getBasedir()
@@ -360,7 +365,7 @@ public class DirectoryScanner
/**
* Sets whether or not the file system should be regarded as case sensitive.
- *
+ *
* @param isCaseSensitive whether or not the file system should be regarded as a case sensitive one
*/
public void setCaseSensitive( final boolean isCaseSensitive )
@@ -370,7 +375,7 @@ public class DirectoryScanner
/**
* Sets whether or not symbolic links should be followed.
- *
+ *
* @param followSymlinks whether or not symbolic links should be followed
*/
public void setFollowSymlinks( final boolean followSymlinks )
@@ -383,7 +388,7 @@ public class DirectoryScanner
* <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 should be
* included. If a non-<code>null</code> list is given, all elements must be non-<code>null</code>.
*/
@@ -416,7 +421,7 @@ public class DirectoryScanner
* <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 given, all elements must be non-<code>null</code>.
*/
@@ -451,7 +456,7 @@ public class DirectoryScanner
/**
* 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 been found so far have been included.
*/
public boolean isEverythingIncluded()
@@ -462,7 +467,7 @@ public class DirectoryScanner
/**
* Scans the base directory for files which match at least one include 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 incorrectly (i.e. if it is <code>null</code>,
* doesn't exist, or isn't a directory).
*/
@@ -482,16 +487,8 @@ public class DirectoryScanner
throw new IllegalStateException( "basedir " + basedir + " is not a directory" );
}
- if ( includes == null )
- {
- // No includes supplied, so set it to 'matches all'
- includes = new String[1];
- includes[0] = "**";
- }
- if ( excludes == null )
- {
- excludes = new String[0];
- }
+ setupDefaultFilters();
+ setupMatchPatterns();
filesIncluded = new ArrayList<String>();
filesNotIncluded = new ArrayList<String>();
@@ -614,19 +611,16 @@ public class DirectoryScanner
final String[] notIncl = dirsNotIncluded.toArray( new String[] {} );
- for ( int i = 0; i < excl.length; i++ )
- {
- if ( !couldHoldIncluded( excl[i] ) )
- {
- scandir( new File( basedir, excl[i] ), excl[i] + File.separator, false );
+ for (String anExcl : excl) {
+ if (!couldHoldIncluded(anExcl)) {
+ scandir(new File(basedir, anExcl), anExcl + File.separator, false);
}
}
- for ( int i = 0; i < notIncl.length; i++ )
+ for (String aNotIncl : notIncl)
{
- if ( !couldHoldIncluded( notIncl[i] ) )
- {
- scandir( new File( basedir, notIncl[i] ), notIncl[i] + File.separator, false );
+ if (!couldHoldIncluded(aNotIncl)) {
+ scandir(new File(basedir, aNotIncl), aNotIncl + File.separator, false);
}
}
@@ -637,7 +631,7 @@ public class DirectoryScanner
* Scans the given directory for files and directories. Found files and directories are placed in their respective
* collections, based on the 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
* dir). Must not be <code>null</code>.
@@ -860,64 +854,43 @@ public class DirectoryScanner
/**
* 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>.
* @return <code>true</code> when the name matches against at least one include pattern, or <code>false</code>
* otherwise.
*/
protected boolean isIncluded( final String name )
{
- for ( final String include : includes )
- {
- if ( matchPath( include, name, isCaseSensitive ) )
- {
- return true;
- }
- }
- return false;
+ return includesPatterns.matches( name, isCaseSensitive );
}
/**
* 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 least one include pattern, or
* <code>false</code> otherwise.
*/
protected boolean couldHoldIncluded( final String name )
{
- for ( final String include : includes )
- {
- if ( matchPatternStart( include, name, isCaseSensitive ) )
- {
- return true;
- }
- }
- return false;
+ return includesPatterns.matchesPatternStart(name, isCaseSensitive);
}
/**
* 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>.
* @return <code>true</code> when the name matches against at least one exclude pattern, or <code>false</code>
* otherwise.
*/
protected boolean isExcluded( final String name )
{
- for ( final String exclude : excludes )
- {
- if ( matchPath( exclude, name, isCaseSensitive ) )
- {
- return true;
- }
- }
- return false;
+ return excludesPatterns.matches(name, isCaseSensitive);
}
/**
* 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>
@@ -931,7 +904,7 @@ public class DirectoryScanner
/**
* 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.
- *
+ *
* @return the names of the files which matched at least one of the include patterns and none of the exclude
* patterns.
*/
@@ -948,7 +921,7 @@ public class DirectoryScanner
/**
* 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 patterns.
* @see #slowScan
*/
@@ -963,7 +936,7 @@ public class DirectoryScanner
* 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 include patterns and at at least one of the
* exclude patterns.
* @see #slowScan
@@ -983,7 +956,7 @@ public class DirectoryScanner
* The names are relative to the base directory. This involves performing a slow scan if one has not already been
* completed.
* </p>
- *
+ *
* @return the names of the files which were deselected.
* @see #slowScan
*/
@@ -997,7 +970,7 @@ public class DirectoryScanner
/**
* 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.
- *
+ *
* @return the names of the directories which matched at least one of the include patterns and none of the exclude
* patterns.
*/
@@ -1010,7 +983,7 @@ public class DirectoryScanner
/**
* Returns the names of the directories 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 directories which matched none of the include patterns.
* @see #slowScan
*/
@@ -1025,7 +998,7 @@ public class DirectoryScanner
* 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 include patterns and at least one of the
* exclude patterns.
* @see #slowScan
@@ -1045,7 +1018,7 @@ public class DirectoryScanner
* The names are relative to the base directory. This involves performing a slow scan if one has not already been
* completed.
* </p>
- *
+ *
* @return the names of the directories which were deselected.
* @see #slowScan
*/
@@ -1082,7 +1055,7 @@ public class DirectoryScanner
* It doesn't really test for symbolic links but whether the canonical and absolute paths of the file are identical
* - this may lead to false positives on some platforms.
* </p>
- *
+ *
* @param parent the parent directory of the file to test
* @param name the name of the file to test.
* @since Ant 1.5
@@ -1096,4 +1069,24 @@ public class DirectoryScanner
.equals( toTest.getCanonicalPath() );
}
+ private void setupDefaultFilters() {
+ if ( includes == null )
+ {
+ // No includes supplied, so set it to 'matches all'
+ includes = new String[1];
+ includes[0] = "**";
+ }
+ if ( excludes == null )
+ {
+ excludes = new String[0];
+ }
+ }
+
+
+ private void setupMatchPatterns()
+ {
+ includesPatterns = MatchPatterns.from( includes );
+ excludesPatterns = MatchPatterns.from( excludes );
+ }
+
}
Added: maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java?rev=1392561&view=auto
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java (added)
+++ maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPattern.java Mon Oct 1 20:01:21 2012
@@ -0,0 +1,128 @@
+package org.apache.maven.shared.utils.io;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+import java.util.StringTokenizer;
+
+/**
+ * Describes a match target for SelectorUtils.
+ * <p/>
+ * Significantly more efficient than using strings, since re-evaluation and re-tokenizing is avoided.
+ *
+ * @author Kristian Rosenvold
+ */
+public class MatchPattern
+{
+ private final String source;
+
+ private final String regexPattern;
+
+ private final String separator;
+
+ private final String[] tokenized;
+
+ private MatchPattern(String source, String separator)
+ {
+ regexPattern = SelectorUtils.isRegexPrefixedPattern( source ) ? source.substring(
+ SelectorUtils.REGEX_HANDLER_PREFIX.length(),
+ source.length() - SelectorUtils.PATTERN_HANDLER_SUFFIX.length() ) : null;
+ this.source =
+ SelectorUtils.isAntPrefixedPattern( source )
+ ? source.substring( SelectorUtils.ANT_HANDLER_PREFIX.length(), source.length()
+ - SelectorUtils.PATTERN_HANDLER_SUFFIX.length() )
+ : source;
+ this.separator = separator;
+ tokenized = tokenizePathToString( this.source, separator );
+ }
+
+
+
+ public boolean matchPath( String str, boolean isCaseSensitive )
+ {
+ if ( regexPattern != null )
+ {
+ return str.matches( regexPattern );
+ }
+ else
+ {
+ return SelectorUtils.matchAntPathPattern( this, str, separator, isCaseSensitive );
+ }
+ }
+
+ boolean matchPath( String str, String[] strDirs, boolean isCaseSensitive )
+ {
+ if ( regexPattern != null )
+ {
+ return str.matches( regexPattern );
+ }
+ else
+ {
+ return SelectorUtils.matchAntPathPattern( getTokenizedPathString(), strDirs, isCaseSensitive );
+ }
+ }
+
+ public boolean matchPatternStart( String str, boolean isCaseSensitive )
+ {
+ if ( regexPattern != null )
+ {
+ // FIXME: ICK! But we can't do partial matches for regex, so we have to reserve judgement until we have
+ // a file to deal with, or we can definitely say this is an exclusion...
+ return true;
+ }
+ else
+ {
+ String altStr = source.replace( '\\', '/' );
+
+ return SelectorUtils.matchAntPathPatternStart( this, str, File.separator, isCaseSensitive )
+ || SelectorUtils.matchAntPathPatternStart( this, altStr, "/", isCaseSensitive );
+ }
+ }
+
+ public String[] getTokenizedPathString()
+ {
+ return tokenized;
+ }
+
+
+ public boolean startsWith( String string )
+ {
+ return source.startsWith( string );
+ }
+
+
+ static String[] tokenizePathToString( String path, String separator )
+ {
+ List<String> ret = new ArrayList<String>();
+ StringTokenizer st = new StringTokenizer( path, separator );
+ while ( st.hasMoreTokens() )
+ {
+ ret.add( st.nextToken() );
+ }
+ return ret.toArray( new String[ret.size()] );
+ }
+
+ public static MatchPattern fromString( String source )
+ {
+ return new MatchPattern( source, File.separator );
+ }
+
+}
Added: maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java?rev=1392561&view=auto
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java (added)
+++ maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/MatchPatterns.java Mon Oct 1 20:01:21 2012
@@ -0,0 +1,98 @@
+package org.apache.maven.shared.utils.io;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * A list of patterns to be matched
+ *
+ * @author Kristian Rosenvold
+ */
+public class MatchPatterns
+{
+ private final MatchPattern[] patterns;
+
+ private MatchPatterns(MatchPattern[] patterns)
+ {
+ this.patterns = patterns;
+ }
+
+ /**
+ * Checks these MatchPatterns against a specified string.
+ * <p/>
+ * Uses far less string tokenization than any of the alternatives.
+ *
+ * @param name The name to look for
+ * @param isCaseSensitive If the comparison is case sensitive
+ * @return true if any of the supplied patterns match
+ */
+ public boolean matches( String name, boolean isCaseSensitive )
+ {
+ String[] tokenized = MatchPattern.tokenizePathToString( name, File.separator );
+ for ( MatchPattern pattern : patterns )
+ {
+ if ( pattern.matchPath( name, tokenized, isCaseSensitive ) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public boolean matchesPatternStart( String name, boolean isCaseSensitive )
+ {
+ for ( MatchPattern includesPattern : patterns )
+ {
+ if ( includesPattern.matchPatternStart( name, isCaseSensitive ) )
+ {
+ return true;
+ }
+ }
+ return false;
+ }
+
+ public static MatchPatterns from( String... sources )
+ {
+ final int length = sources.length;
+ MatchPattern[] result = new MatchPattern[length];
+ for ( int i = 0; i < length; i++ )
+ {
+ result[i] = MatchPattern.fromString( sources[i] );
+ }
+ return new MatchPatterns( result );
+ }
+
+ public static MatchPatterns from( Iterable<String> strings )
+ {
+ return new MatchPatterns( getMatchPatterns( strings ) );
+ }
+
+ private static MatchPattern[] getMatchPatterns( Iterable<String> items )
+ {
+ List<MatchPattern> result = new ArrayList<MatchPattern>();
+ for ( String string : items )
+ {
+ result.add( MatchPattern.fromString( string ) );
+ }
+ return result.toArray( new MatchPattern[result.size()] );
+ }
+
+}
Modified: maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java?rev=1392561&r1=1392560&r2=1392561&view=diff
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java (original)
+++ maven/shared/trunk/maven-shared-utils/src/main/java/org/apache/maven/shared/utils/io/SelectorUtils.java Mon Oct 1 20:01:21 2012
@@ -21,6 +21,8 @@ package org.apache.maven.shared.utils.io
import java.io.File;
+import java.util.ArrayList;
+import java.util.List;
import java.util.StringTokenizer;
import java.util.Vector;
@@ -108,8 +110,7 @@ public final class SelectorUtils
public static boolean matchPatternStart( String pattern, String str,
boolean isCaseSensitive )
{
- if ( pattern.length() > ( REGEX_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1 )
- && pattern.startsWith( REGEX_HANDLER_PREFIX ) && pattern.endsWith( PATTERN_HANDLER_SUFFIX ) )
+ if ( isRegexPrefixedPattern( pattern ) )
{
// FIXME: ICK! But we can't do partial matches for regex, so we have to reserve judgement until we have
// a file to deal with, or we can definitely say this is an exclusion...
@@ -117,8 +118,7 @@ public final class SelectorUtils
}
else
{
- if ( pattern.length() > ( ANT_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1 )
- && pattern.startsWith( ANT_HANDLER_PREFIX ) && pattern.endsWith( PATTERN_HANDLER_SUFFIX ) )
+ if ( isAntPrefixedPattern( pattern ) )
{
pattern =
pattern.substring( ANT_HANDLER_PREFIX.length(), pattern.length() - PATTERN_HANDLER_SUFFIX.length() );
@@ -137,8 +137,7 @@ public final class SelectorUtils
// File.separator.
// When pattern starts with a File.separator, str has to start with a
// File.separator.
- if ( str.startsWith( separator ) !=
- pattern.startsWith( separator ) )
+ if ( separatorPatternStartSlashMismatch( pattern, str, separator ) )
{
return false;
}
@@ -685,4 +684,218 @@ public final class SelectorUtils
}
return result.toString();
}
+
+ static boolean matchAntPathPatternStart( MatchPattern pattern, String str, String separator,
+ boolean isCaseSensitive )
+ {
+ if ( separatorPatternStartSlashMismatch( pattern, str, separator ) )
+ {
+ return false;
+ }
+
+ return matchAntPathPatternStart( pattern.getTokenizedPathString(), str, separator, isCaseSensitive );
+ }
+
+ private static String[] tokenizePathToString( String path, String separator )
+ {
+ List<String> ret = new ArrayList<String>();
+ StringTokenizer st = new StringTokenizer( path, separator );
+ while ( st.hasMoreTokens() )
+ {
+ ret.add( st.nextToken() );
+ }
+ return ret.toArray(new String[ret.size()]);
+ }
+
+ static boolean matchAntPathPatternStart( String[] patDirs, String str, String separator, boolean isCaseSensitive )
+ {
+ String[] strDirs = tokenizePathToString( str, separator );
+
+ 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++;
+ }
+
+ return strIdxStart > strIdxEnd || patIdxStart <= patIdxEnd;
+ }
+
+ private static boolean separatorPatternStartSlashMismatch( MatchPattern matchPattern, String str, String separator )
+ {
+ return str.startsWith( separator ) != matchPattern.startsWith( separator );
+ }
+
+ private static boolean separatorPatternStartSlashMismatch( String pattern, String str, String separator )
+ {
+ return str.startsWith( separator ) != pattern.startsWith( separator );
+ }
+
+
+ static boolean matchAntPathPattern( String[] patDirs, String[] strDirs, boolean isCaseSensitive )
+ {
+ 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
+ for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+ {
+ if ( !patDirs[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 = patDirs[patIdxEnd];
+ if ( patDir.equals( "**" ) )
+ {
+ break;
+ }
+ if ( !match( patDir, strDirs[strIdxEnd], isCaseSensitive ) )
+ {
+ return false;
+ }
+ patIdxEnd--;
+ strIdxEnd--;
+ }
+ if ( strIdxStart > strIdxEnd )
+ {
+ // String is exhausted
+ for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+ {
+ if ( !patDirs[i].equals( "**" ) )
+ {
+ 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 )
+ {
+ return false;
+ }
+
+ patIdxStart = patIdxTmp;
+ strIdxStart = foundIdx + patLength;
+ }
+
+ for ( int i = patIdxStart; i <= patIdxEnd; i++ )
+ {
+ if ( !patDirs[i].equals( "**" ) )
+ {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
+ static boolean isRegexPrefixedPattern( String pattern )
+ {
+ return pattern.length() > ( REGEX_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1 )
+ && pattern.startsWith( REGEX_HANDLER_PREFIX ) && pattern.endsWith( PATTERN_HANDLER_SUFFIX );
+ }
+ static boolean isAntPrefixedPattern( String pattern )
+ {
+ return pattern.length() > ( ANT_HANDLER_PREFIX.length() + PATTERN_HANDLER_SUFFIX.length() + 1 )
+ && pattern.startsWith( ANT_HANDLER_PREFIX ) && pattern.endsWith( PATTERN_HANDLER_SUFFIX );
+ }
+
+ static boolean matchAntPathPattern( MatchPattern matchPattern, String str, String separator,
+ boolean isCaseSensitive )
+ {
+ if ( separatorPatternStartSlashMismatch( matchPattern, str, separator ) )
+ {
+ return false;
+ }
+ String[] patDirs = matchPattern.getTokenizedPathString();
+ String[] strDirs = tokenizePathToString( str, separator );
+ return matchAntPathPattern( patDirs, strDirs, isCaseSensitive );
+ }
}
Added: maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternTest.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternTest.java?rev=1392561&view=auto
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternTest.java (added)
+++ maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternTest.java Mon Oct 1 20:01:21 2012
@@ -0,0 +1,37 @@
+package org.apache.maven.shared.utils.io;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.junit.Test;
+import static org.junit.Assert.*;
+
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class MatchPatternTest {
+ @Test
+ public void matchPath()
+ throws Exception
+ {
+ MatchPattern mp = MatchPattern.fromString( "ABC*" );
+ assertTrue(mp.matchPath( "ABCD", true ));
+ }
+
+}
Added: maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternsTest.java
URL: http://svn.apache.org/viewvc/maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternsTest.java?rev=1392561&view=auto
==============================================================================
--- maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternsTest.java (added)
+++ maven/shared/trunk/maven-shared-utils/src/test/java/org/apache/maven/shared/utils/io/MatchPatternsTest.java Mon Oct 1 20:01:21 2012
@@ -0,0 +1,38 @@
+package org.apache.maven.shared.utils.io;
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+import org.junit.Test;
+
+import static org.junit.Assert.*;
+
+/**
+ * @author Kristian Rosenvold
+ */
+public class MatchPatternsTest {
+ @Test
+ public void matches()
+ throws Exception
+ {
+ MatchPatterns from = MatchPatterns.from( "ABC**", "CDE**" );
+ assertTrue( from.matches( "ABCDE", true ) );
+ assertTrue( from.matches( "CDEF", true ) );
+ assertFalse( from.matches( "XYZ", true ) );
+
+ }
+}