MSHARED-109 : Add ranges support in filters
Submitted by: Benoit Lafontaine
git-svn-id: https://svn.apache.org/repos/asf/maven/shared/trunk@803321 13f79535-47bb-0310-9956-ffa450edef68
diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilter.java b/src/main/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilter.java
index bd476e4..05a214e 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilter.java
+++ b/src/main/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilter.java
@@ -21,6 +21,9 @@
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
import java.util.Iterator;
import java.util.List;
@@ -171,6 +174,11 @@
matches = token.startsWith( prefix );
}
+ // support versions range
+ else if ( pattern.startsWith( "[" ) || pattern.startsWith( "(" ))
+ {
+ matches = isVersionIncludedInRange(token, pattern);
+ }
// support exact match
else
{
@@ -179,4 +187,13 @@
return matches;
}
+
+ private boolean isVersionIncludedInRange(final String version, final String range) {
+ try {
+ return VersionRange.createFromVersionSpec(range).containsVersion(new DefaultArtifactVersion(version));
+ } catch (InvalidVersionSpecificationException e) {
+ return false;
+ }
+ }
+
}
diff --git a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
index ce9d9e5..c81c262 100644
--- a/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
+++ b/src/main/java/org/apache/maven/shared/artifact/filter/PatternIncludesArtifactFilter.java
@@ -27,6 +27,9 @@
import org.apache.maven.artifact.Artifact;
import org.apache.maven.artifact.ArtifactUtils;
import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.VersionRange;
import org.codehaus.plexus.logging.Logger;
import org.codehaus.plexus.util.StringUtils;
@@ -162,67 +165,107 @@
return false;
}
- private boolean matchAgainst( String value, List patterns, boolean regionMatch )
+ private boolean matchAgainst( String value, List patterns, boolean regionMatch ) {
+ for (Iterator iterator = patterns.iterator(); iterator.hasNext();) {
+ String pattern = (String) iterator.next();
+
+ String[] patternTokens = pattern.split( ":" );
+ String[] tokens = value.split( ":" );
+
+ // fail immediately if pattern tokens outnumber tokens to match
+ boolean matched = ( patternTokens.length <= tokens.length );
+
+ for ( int i = 0; matched && i < patternTokens.length; i++ )
+ {
+ matched = matches( tokens[i], patternTokens[i] );
+ }
+
+// // case of starting '*' like '*:jar:*'
+ if (!matched && patternTokens.length < tokens.length && patternTokens.length>0 && "*".equals(patternTokens[0]))
+ {
+ matched=true;
+ for ( int i = 0; matched && i < patternTokens.length; i++ )
+ {
+ matched = matches( tokens[i+(tokens.length-patternTokens.length)], patternTokens[i] );
+ }
+ }
+
+ if (matched) {
+ patternsTriggered.add( pattern );
+ return true;
+ }
+
+ if ( regionMatch && value.indexOf( pattern ) > -1 )
+ {
+ patternsTriggered.add( pattern );
+ return true;
+ }
+
+ }
+ return false;
+
+ }
+
+ /**
+ * Gets whether the specified token matches the specified pattern segment.
+ *
+ * @param token
+ * the token to check
+ * @param pattern
+ * the pattern segment to match, as defined above
+ * @return <code>true</code> if the specified token is matched by the specified pattern segment
+ */
+ private boolean matches( String token, final String pattern )
{
- patternLoop:
- for ( Iterator i = patterns.iterator(); i.hasNext(); )
+ boolean matches;
+
+ // support full wildcard and implied wildcard
+ if ( "*".equals( pattern ) || pattern.length() == 0 )
{
- // TODO: what about wildcards? Just specifying groups? versions?
- String pattern = (String) i.next();
+ matches = true;
+ }
+ // support contains wildcard
+ else if ( pattern.startsWith( "*" ) && pattern.endsWith( "*" ) )
+ {
+ String contains = pattern.substring( 1, pattern.length() - 1 );
- // don't allow wildcards in region-matched searches...i.e. in transitive dependencies.
-// if ( regionMatch && ( pattern.indexOf( '*' ) > -1 ) )
-// {
-// continue;
-// }
+ matches = ( token.indexOf( contains ) != -1 );
+ }
+ // support leading wildcard
+ else if ( pattern.startsWith( "*" ) )
+ {
+ String suffix = pattern.substring( 1, pattern.length() );
- if ( value.equals( pattern ) )
- {
- patternsTriggered.add( pattern );
- return true;
- }
- else if ( pattern.indexOf( '*' ) > -1 )
- {
- String[] subPatterns = pattern.split( "\\*" );
- int[] idxes = new int[subPatterns.length];
+ matches = token.endsWith( suffix );
+ }
+ // support trailing wildcard
+ else if ( pattern.endsWith( "*" ) )
+ {
+ String prefix = pattern.substring( 0, pattern.length() - 1 );
- for ( int j = 0; j < subPatterns.length; j++ )
- {
- String subPattern = subPatterns[j];
- if ( subPattern.endsWith( "*" ) )
- {
- subPattern = subPattern.substring( 0, subPattern.length() - 1 );
- }
-
- if ( ( subPattern == null ) || ( subPattern.length() < 1 ) )
- {
- idxes[j] = j == 0 ? 0 : idxes[j - 1];
-
- continue;
- }
-
- int lastIdx = j == 0 ? 0 : idxes[j - 1];
-
- idxes[j] = value.indexOf( subPattern, lastIdx );
-
- if ( idxes[j] < 0 )
- {
- patternsTriggered.add( pattern );
- continue patternLoop;
- }
- }
-
- return true;
- }
- else if ( regionMatch && value.indexOf( pattern ) > -1 )
- {
- patternsTriggered.add( pattern );
- return true;
- }
+ matches = token.startsWith( prefix );
+ }
+ // support versions range
+ else if ( pattern.startsWith( "[" ) || pattern.startsWith( "(" ))
+ {
+ matches = isVersionIncludedInRange(token, pattern);
+ }
+ // support exact match
+ else
+ {
+ matches = token.equals( pattern );
}
- return false;
+ return matches;
}
+
+ private boolean isVersionIncludedInRange(final String version, final String range) {
+ try {
+ return VersionRange.createFromVersionSpec(range).containsVersion(new DefaultArtifactVersion(version));
+ } catch (InvalidVersionSpecificationException e) {
+ return false;
+ }
+ }
public void reportMissedCriteria( Logger logger )
{
diff --git a/src/test/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilterTest.java b/src/test/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilterTest.java
index 26f23a8..39f8739 100644
--- a/src/test/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilterTest.java
+++ b/src/test/java/org/apache/maven/shared/artifact/filter/AbstractStrictPatternArtifactFilterTest.java
@@ -42,7 +42,7 @@
{
// fields -----------------------------------------------------------------
- private Artifact artifact;
+ protected Artifact artifact;
// TestCase methods -------------------------------------------------------
@@ -317,7 +317,31 @@
assertIncluded( ":::*-SNAPSHOT" );
}
+
+ public void testRangeVersion()
+ {
+ artifact = createArtifact( "groupId", "artifactId", "type", "1.0.1" );
+ assertIncluded( "groupId:artifactId:type:[1.0.1]");
+ assertIncluded( "groupId:artifactId:type:[1.0,1.1)");
+
+ assertExcluded( "groupId:artifactId:type:[1.5,)");
+ assertExcluded( "groupId:artifactId:type:(,1.0],[1.2,)");
+ assertExcluded( "groupId:artifactId:type:(,1.0],[1.2,)");
+ }
+ public void testWildcardsWithRangeVersion()
+ {
+ artifact = createArtifact( "groupId", "artifactId", "type", "1.0.1" );
+ assertIncluded( ":::[1.0.1]");
+ assertIncluded( ":artifact*:*:[1.0,1.1)");
+
+ assertExcluded( "*group*:*:t*e:[1.5,)");
+
+ artifact = createArtifact( "test", "uf", "jar", "0.2.0" );
+ assertIncluded( "test:*:*:[0.0.2,)" );
+
+ }
+
// protected methods ------------------------------------------------------
/**
diff --git a/src/test/java/org/apache/maven/shared/artifact/filter/PatternArtifactFilterTCK.java b/src/test/java/org/apache/maven/shared/artifact/filter/PatternArtifactFilterTCK.java
index 9ff3c21..36e18cb 100644
--- a/src/test/java/org/apache/maven/shared/artifact/filter/PatternArtifactFilterTCK.java
+++ b/src/test/java/org/apache/maven/shared/artifact/filter/PatternArtifactFilterTCK.java
@@ -390,6 +390,8 @@
String artifactId;
+ String version;
+
List dependencyTrail;
String type;
@@ -412,7 +414,7 @@
artifact = (Artifact) control.getMock();
enableGetDependencyConflictId();
- enableGetGroupIdAndArtifactId();
+ enableGetGroupIdArtifactIdAndVersion();
enableGetId();
if ( dependencyTrail != null )
@@ -449,13 +451,17 @@
control.setReturnValue( groupId + ":" + artifactId + ":" + type, MockControl.ONE_OR_MORE );
}
- void enableGetGroupIdAndArtifactId()
+ void enableGetGroupIdArtifactIdAndVersion()
{
artifact.getGroupId();
control.setReturnValue( groupId, MockControl.ONE_OR_MORE );
artifact.getArtifactId();
control.setReturnValue( artifactId, MockControl.ONE_OR_MORE );
+
+ artifact.getVersion();
+ control.setReturnValue( version , MockControl.ZERO_OR_MORE );
+
}
}