1 package org.apache.maven.plugins.enforcer;
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 java.util.List;
23
24 import org.apache.maven.artifact.versioning.ArtifactVersion;
25 import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
26 import org.apache.maven.artifact.versioning.Restriction;
27 import org.apache.maven.artifact.versioning.VersionRange;
28 import org.apache.maven.enforcer.rule.api.EnforcerRule;
29 import org.apache.maven.enforcer.rule.api.EnforcerRuleException;
30 import org.apache.maven.plugin.logging.Log;
31 import org.codehaus.plexus.util.StringUtils;
32
33 /**
34 * Contains the common code to compare a version against a version range.
35 *
36 * @author <a href="mailto:brianf@apache.org">Brian Fox</a>
37 * @version $Id: AbstractVersionEnforcer.java 1634140 2014-10-24 21:23:01Z khmarbaise $
38 */
39 public abstract class AbstractVersionEnforcer
40 extends AbstractStandardEnforcerRule
41 {
42
43 /**
44 * Specify the required version. Some examples are:
45 * <ul>
46 * <li><code>2.0.4</code> Version 2.0.4 and higher (different from Maven meaning)</li>
47 * <li><code>[2.0,2.1)</code> Versions 2.0 (included) to 2.1 (not included)</li>
48 * <li><code>[2.0,2.1]</code> Versions 2.0 to 2.1 (both included)</li>
49 * <li><code>[2.0.5,)</code> Versions 2.0.5 and higher</li>
50 * <li><code>(,2.0.5],[2.1.1,)</code> Versions up to 2.0.5 (included) and 2.1.1 or higher</li>
51 * </ul>
52 *
53 * @see {@link #setVersion(String)}
54 * @see {@link #getVersion()}
55 */
56 private String version;
57
58 /**
59 * Compares the specified version to see if it is allowed by the defined version range.
60 *
61 * @param log the log
62 * @param variableName name of variable to use in messages (Example: "Maven" or "Java" etc).
63 * @param requiredVersionRange range of allowed versions.
64 * @param actualVersion the version to be checked.
65 * @throws EnforcerRuleException the enforcer rule exception
66 */
67 // CHECKSTYLE_OFF: LineLength
68 public void enforceVersion( Log log, String variableName, String requiredVersionRange, ArtifactVersion actualVersion )
69 throws EnforcerRuleException
70 // CHECKSTYLE_ON: LineLength
71 {
72 if ( StringUtils.isEmpty( requiredVersionRange ) )
73 {
74 throw new EnforcerRuleException( variableName + " version can't be empty." );
75 }
76 else
77 {
78
79 VersionRange vr;
80 String msg = "Detected " + variableName + " Version: " + actualVersion;
81
82 // short circuit check if the strings are exactly equal
83 if ( actualVersion.toString().equals( requiredVersionRange ) )
84 {
85 log.debug( msg + " is allowed in the range " + requiredVersionRange + "." );
86 }
87 else
88 {
89 try
90 {
91 vr = VersionRange.createFromVersionSpec( requiredVersionRange );
92
93 if ( containsVersion( vr, actualVersion ) )
94 {
95 log.debug( msg + " is allowed in the range " + requiredVersionRange + "." );
96 }
97 else
98 {
99 String message = getMessage();
100
101 if ( StringUtils.isEmpty( message ) )
102 {
103 message = msg + " is not in the allowed range " + vr + ".";
104 }
105
106 throw new EnforcerRuleException( message );
107 }
108 }
109 catch ( InvalidVersionSpecificationException e )
110 {
111 throw new EnforcerRuleException( "The requested " + variableName + " version "
112 + requiredVersionRange + " is invalid.", e );
113 }
114 }
115 }
116 }
117
118 /**
119 * Copied from Artifact.VersionRange. This is tweaked to handle singular ranges properly. Currently the default
120 * containsVersion method assumes a singular version means allow everything. This method assumes that "2.0.4" ==
121 * "[2.0.4,)"
122 *
123 * @param allowedRange range of allowed versions.
124 * @param theVersion the version to be checked.
125 * @return true if the version is contained by the range.
126 */
127 public static boolean containsVersion( VersionRange allowedRange, ArtifactVersion theVersion )
128 {
129 boolean matched = false;
130 ArtifactVersion recommendedVersion = allowedRange.getRecommendedVersion();
131 if ( recommendedVersion == null )
132 {
133 @SuppressWarnings( "unchecked" )
134 List<Restriction> restrictions = allowedRange.getRestrictions();
135 for ( Restriction restriction : restrictions )
136 {
137 if ( restriction.containsVersion( theVersion ) )
138 {
139 matched = true;
140 break;
141 }
142 }
143 }
144 else
145 {
146 // only singular versions ever have a recommendedVersion
147 @SuppressWarnings( "unchecked" )
148 int compareTo = recommendedVersion.compareTo( theVersion );
149 matched = ( compareTo <= 0 );
150 }
151 return matched;
152 }
153
154 /*
155 * (non-Javadoc)
156 * @see org.apache.maven.enforcer.rule.api.EnforcerRule#getCacheId()
157 */
158 public String getCacheId()
159 {
160 if ( StringUtils.isNotEmpty( version ) )
161 {
162 // return the hashcodes of the parameter that matters
163 return "" + version.hashCode();
164 }
165 else
166 {
167 return "0";
168 }
169
170 }
171
172 /*
173 * (non-Javadoc)
174 * @see org.apache.maven.enforcer.rule.api.EnforcerRule#isCacheable()
175 */
176 public boolean isCacheable()
177 {
178 // the maven version is not going to change between projects in the same build.
179 return true;
180 }
181
182 /*
183 * (non-Javadoc)
184 * @see
185 * org.apache.maven.enforcer.rule.api.EnforcerRule#isResultValid(org.apache.maven.enforcer.rule.api.EnforcerRule)
186 */
187 public boolean isResultValid( EnforcerRule theCachedRule )
188 {
189 // i will always return the hash of the parameters as my id. If my parameters are the same, this
190 // rule must always have the same result.
191 return true;
192 }
193
194 /**
195 * Gets the required version.
196 *
197 * @return the required version
198 */
199 public final String getVersion()
200 {
201 return this.version;
202 }
203
204 /**
205 * Specify the required version. Some examples are:
206 * <ul>
207 * <li><code>2.0.4</code> Version 2.0.4 and higher (different from Maven meaning)</li>
208 * <li><code>[2.0,2.1)</code> Versions 2.0 (included) to 2.1 (not included)</li>
209 * <li><code>[2.0,2.1]</code> Versions 2.0 to 2.1 (both included)</li>
210 * <li><code>[2.0.5,)</code> Versions 2.0.5 and higher</li>
211 * <li><code>(,2.0.5],[2.1.1,)</code> Versions up to 2.0.5 (included) and 2.1.1 or higher</li>
212 * </ul>
213 *
214 * @param theVersion the required version to set
215 */
216 public final void setVersion( String theVersion )
217 {
218 this.version = theVersion;
219 }
220
221 }