View Javadoc

1   package org.apache.maven.shared.artifact.filter;
2   
3   /*
4    * Licensed to the Apache Software Foundation (ASF) under one
5    * or more contributor license agreements.  See the NOTICE file
6    * distributed with this work for additional information
7    * regarding copyright ownership.  The ASF licenses this file
8    * to you under the Apache License, Version 2.0 (the
9    * "License"); you may not use this file except in compliance
10   * with the License.  You may obtain a copy of the License at
11   *
12   *  http://www.apache.org/licenses/LICENSE-2.0
13   *
14   * Unless required by applicable law or agreed to in writing,
15   * software distributed under the License is distributed on an
16   * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
17   * KIND, either express or implied.  See the License for the
18   * specific language governing permissions and limitations
19   * under the License.
20   */
21  
22  import org.apache.maven.artifact.Artifact;
23  import org.apache.maven.artifact.resolver.filter.ArtifactFilter;
24  import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
25  import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
26  import org.apache.maven.artifact.versioning.VersionRange;
27  
28  import java.util.Iterator;
29  import java.util.List;
30  
31  /**
32   * Filter to include or exclude artifacts from a list of patterns. The artifact pattern syntax is of the form:
33   * 
34   * <pre>
35   * [groupId]:[artifactId]:[type]:[version]
36   * </pre>
37   * 
38   * <p>
39   * Where each pattern segment is optional and supports full and partial <code>*</code> wildcards. An empty pattern
40   * segment is treated as an implicit wildcard.
41   * </p>
42   * 
43   * <p>
44   * For example, <code>org.apache.*</code> would match all artifacts whose group id started with
45   * <code>org.apache.</code>, and <code>:::*-SNAPSHOT</code> would match all snapshot artifacts.
46   * </p>
47   * 
48   * @author <a href="mailto:markhobson@gmail.com">Mark Hobson</a>
49   * @version $Id: AbstractStrictPatternArtifactFilter.java 803321 2009-08-11 23:09:24Z aheritier $
50   */
51  public abstract class AbstractStrictPatternArtifactFilter implements ArtifactFilter
52  {
53      // fields -----------------------------------------------------------------
54  
55      /**
56       * The list of artifact patterns to match, as described above.
57       */
58      private final List patterns;
59  
60      /**
61       * Whether this filter should include or exclude artifacts that match the patterns.
62       */
63      private final boolean include;
64  
65      // constructors -----------------------------------------------------------
66  
67      /**
68       * Creates a new filter that matches the specified artifact patterns and includes or excludes them according to the
69       * specified flag.
70       * 
71       * @param patterns
72       *            the list of artifact patterns to match, as described above
73       * @param include
74       *            <code>true</code> to include artifacts that match the patterns, or <code>false</code> to exclude
75       *            them
76       */
77      public AbstractStrictPatternArtifactFilter( List patterns, boolean include )
78      {
79          this.patterns = patterns;
80          this.include = include;
81      }
82  
83      // ArtifactFilter methods -------------------------------------------------
84  
85      /*
86       * @see org.apache.maven.artifact.resolver.filter.ArtifactFilter#include(org.apache.maven.artifact.Artifact)
87       */
88      public boolean include( Artifact artifact )
89      {
90          boolean matched = false;
91  
92          for ( Iterator i = patterns.iterator(); i.hasNext() & !matched; )
93          {
94              String pattern = (String) i.next();
95  
96              if ( include( artifact, pattern ) )
97              {
98                  matched = true;
99              }
100         }
101 
102         return include ? matched : !matched;
103     }
104 
105     // private methods --------------------------------------------------------
106 
107     /**
108      * Gets whether the specified artifact matches the specified pattern.
109      * 
110      * @param artifact
111      *            the artifact to check
112      * @param pattern
113      *            the pattern to match, as defined above
114      * @return <code>true</code> if the specified artifact is matched by the specified pattern
115      */
116     private boolean include( Artifact artifact, String pattern )
117     {
118         String[] tokens = new String[] {
119             artifact.getGroupId(),
120             artifact.getArtifactId(),
121             artifact.getType(),
122             artifact.getBaseVersion()
123         };
124 
125         String[] patternTokens = pattern.split( ":" );
126 
127         // fail immediately if pattern tokens outnumber tokens to match
128         boolean matched = ( patternTokens.length <= tokens.length );
129 
130         for ( int i = 0; matched && i < patternTokens.length; i++ )
131         {
132             matched = matches( tokens[i], patternTokens[i] );
133         }
134 
135         return matched;
136     }
137 
138     /**
139      * Gets whether the specified token matches the specified pattern segment.
140      * 
141      * @param token
142      *            the token to check
143      * @param pattern
144      *            the pattern segment to match, as defined above
145      * @return <code>true</code> if the specified token is matched by the specified pattern segment
146      */
147     private boolean matches( String token, String pattern )
148     {
149         boolean matches;
150 
151         // support full wildcard and implied wildcard
152         if ( "*".equals( pattern ) || pattern.length() == 0 )
153         {
154             matches = true;
155         }
156         // support contains wildcard
157         else if ( pattern.startsWith( "*" ) && pattern.endsWith( "*" ) )
158         {
159             String contains = pattern.substring( 1, pattern.length() - 1 );
160 
161             matches = ( token.indexOf( contains ) != -1 );
162         }
163         // support leading wildcard
164         else if ( pattern.startsWith( "*" ) )
165         {
166             String suffix = pattern.substring( 1, pattern.length() );
167 
168             matches = token.endsWith( suffix );
169         }
170         // support trailing wildcard
171         else if ( pattern.endsWith( "*" ) )
172         {
173             String prefix = pattern.substring( 0, pattern.length() - 1 );
174 
175             matches = token.startsWith( prefix );
176         }
177         // support versions range 
178         else if ( pattern.startsWith( "[" ) || pattern.startsWith( "(" ))
179         {
180         	matches = isVersionIncludedInRange(token, pattern);
181         }
182         // support exact match
183         else
184         {
185             matches = token.equals( pattern );
186         }
187 
188         return matches;
189     }
190     
191     private boolean isVersionIncludedInRange(final String version, final String range) {
192     	try {
193 			return VersionRange.createFromVersionSpec(range).containsVersion(new DefaultArtifactVersion(version));
194 		} catch (InvalidVersionSpecificationException e) {
195 			return false;
196 		}
197 	}
198 
199 }