diff options
Diffstat (limited to 'framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning')
7 files changed, 1634 insertions, 0 deletions
diff --git a/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ArtifactVersion.java b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ArtifactVersion.java new file mode 100644 index 00000000..5b516a91 --- /dev/null +++ b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ArtifactVersion.java @@ -0,0 +1,42 @@ +package org.apache.maven.artifact.versioning; + +/* + * 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. + */ + +/** + * Describes an artifact version in terms of its components, converts it to/from a string and + * compares two versions. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + */ +public interface ArtifactVersion + extends Comparable<ArtifactVersion> +{ + int getMajorVersion(); + + int getMinorVersion(); + + int getIncrementalVersion(); + + int getBuildNumber(); + + String getQualifier(); + + void parseVersion( String version ); +} diff --git a/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java new file mode 100644 index 00000000..67a46960 --- /dev/null +++ b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/ComparableVersion.java @@ -0,0 +1,503 @@ +package org.apache.maven.artifact.versioning; + +/* + * 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.math.BigInteger; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Iterator; +import java.util.List; +import java.util.Locale; +import java.util.Properties; +import java.util.Stack; + +/** + * Generic implementation of version comparison. + * + * <p>Features: + * <ul> + * <li>mixing of '<code>-</code>' (dash) and '<code>.</code>' (dot) separators,</li> + * <li>transition between characters and digits also constitutes a separator: + * <code>1.0alpha1 => [1, 0, alpha, 1]</code></li> + * <li>unlimited number of version components,</li> + * <li>version components in the text can be digits or strings,</li> + * <li>strings are checked for well-known qualifiers and the qualifier ordering is used for version ordering. + * Well-known qualifiers (case insensitive) are:<ul> + * <li><code>alpha</code> or <code>a</code></li> + * <li><code>beta</code> or <code>b</code></li> + * <li><code>milestone</code> or <code>m</code></li> + * <li><code>rc</code> or <code>cr</code></li> + * <li><code>snapshot</code></li> + * <li><code>(the empty string)</code> or <code>ga</code> or <code>final</code></li> + * <li><code>sp</code></li> + * </ul> + * Unknown qualifiers are considered after known qualifiers, with lexical order (always case insensitive), + * </li> + * <li>a dash usually precedes a qualifier, and is always less important than something preceded with a dot.</li> + * </ul></p> + * + * @see <a href="https://cwiki.apache.org/confluence/display/MAVENOLD/Versioning">"Versioning" on Maven Wiki</a> + * @author <a href="mailto:kenney@apache.org">Kenney Westerhof</a> + * @author <a href="mailto:hboutemy@apache.org">Hervé Boutemy</a> + */ +public class ComparableVersion + implements Comparable<ComparableVersion> +{ + private String value; + + private String canonical; + + private ListItem items; + + private interface Item + { + int INTEGER_ITEM = 0; + int STRING_ITEM = 1; + int LIST_ITEM = 2; + + int compareTo( Item item ); + + int getType(); + + boolean isNull(); + } + + /** + * Represents a numeric item in the version item list. + */ + private static class IntegerItem + implements Item + { + private static final BigInteger BIG_INTEGER_ZERO = new BigInteger( "0" ); + + private final BigInteger value; + + public static final IntegerItem ZERO = new IntegerItem(); + + private IntegerItem() + { + this.value = BIG_INTEGER_ZERO; + } + + public IntegerItem( String str ) + { + this.value = new BigInteger( str ); + } + + public int getType() + { + return INTEGER_ITEM; + } + + public boolean isNull() + { + return BIG_INTEGER_ZERO.equals( value ); + } + + public int compareTo( Item item ) + { + if ( item == null ) + { + return BIG_INTEGER_ZERO.equals( value ) ? 0 : 1; // 1.0 == 1, 1.1 > 1 + } + + switch ( item.getType() ) + { + case INTEGER_ITEM: + return value.compareTo( ( (IntegerItem) item ).value ); + + case STRING_ITEM: + return 1; // 1.1 > 1-sp + + case LIST_ITEM: + return 1; // 1.1 > 1-1 + + default: + throw new RuntimeException( "invalid item: " + item.getClass() ); + } + } + + public String toString() + { + return value.toString(); + } + } + + /** + * Represents a string in the version item list, usually a qualifier. + */ + private static class StringItem + implements Item + { + private static final String[] QUALIFIERS = { "alpha", "beta", "milestone", "rc", "snapshot", "", "sp" }; + + @SuppressWarnings( "checkstyle:constantname" ) + private static final List<String> _QUALIFIERS = Arrays.asList( QUALIFIERS ); + + private static final Properties ALIASES = new Properties(); + static + { + ALIASES.put( "ga", "" ); + ALIASES.put( "final", "" ); + ALIASES.put( "cr", "rc" ); + } + + /** + * A comparable value for the empty-string qualifier. This one is used to determine if a given qualifier makes + * the version older than one without a qualifier, or more recent. + */ + private static final String RELEASE_VERSION_INDEX = String.valueOf( _QUALIFIERS.indexOf( "" ) ); + + private String value; + + public StringItem( String value, boolean followedByDigit ) + { + if ( followedByDigit && value.length() == 1 ) + { + // a1 = alpha-1, b1 = beta-1, m1 = milestone-1 + switch ( value.charAt( 0 ) ) + { + case 'a': + value = "alpha"; + break; + case 'b': + value = "beta"; + break; + case 'm': + value = "milestone"; + break; + default: + } + } + this.value = ALIASES.getProperty( value , value ); + } + + public int getType() + { + return STRING_ITEM; + } + + public boolean isNull() + { + return ( comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX ) == 0 ); + } + + /** + * Returns a comparable value for a qualifier. + * + * This method takes into account the ordering of known qualifiers then unknown qualifiers with lexical + * ordering. + * + * just returning an Integer with the index here is faster, but requires a lot of if/then/else to check for -1 + * or QUALIFIERS.size and then resort to lexical ordering. Most comparisons are decided by the first character, + * so this is still fast. If more characters are needed then it requires a lexical sort anyway. + * + * @param qualifier + * @return an equivalent value that can be used with lexical comparison + */ + public static String comparableQualifier( String qualifier ) + { + int i = _QUALIFIERS.indexOf( qualifier ); + + return i == -1 ? ( _QUALIFIERS.size() + "-" + qualifier ) : String.valueOf( i ); + } + + public int compareTo( Item item ) + { + if ( item == null ) + { + // 1-rc < 1, 1-ga > 1 + return comparableQualifier( value ).compareTo( RELEASE_VERSION_INDEX ); + } + switch ( item.getType() ) + { + case INTEGER_ITEM: + return -1; // 1.any < 1.1 ? + + case STRING_ITEM: + return comparableQualifier( value ).compareTo( comparableQualifier( ( (StringItem) item ).value ) ); + + case LIST_ITEM: + return -1; // 1.any < 1-1 + + default: + throw new RuntimeException( "invalid item: " + item.getClass() ); + } + } + + public String toString() + { + return value; + } + } + + /** + * Represents a version list item. This class is used both for the global item list and for sub-lists (which start + * with '-(number)' in the version specification). + */ + private static class ListItem + extends ArrayList<Item> + implements Item + { + public int getType() + { + return LIST_ITEM; + } + + public boolean isNull() + { + return ( size() == 0 ); + } + + void normalize() + { + for ( int i = size() - 1; i >= 0; i-- ) + { + Item lastItem = get( i ); + + if ( lastItem.isNull() ) + { + // remove null trailing items: 0, "", empty list + remove( i ); + } + else if ( !( lastItem instanceof ListItem ) ) + { + break; + } + } + } + + public int compareTo( Item item ) + { + if ( item == null ) + { + if ( size() == 0 ) + { + return 0; // 1-0 = 1- (normalize) = 1 + } + Item first = get( 0 ); + return first.compareTo( null ); + } + switch ( item.getType() ) + { + case INTEGER_ITEM: + return -1; // 1-1 < 1.0.x + + case STRING_ITEM: + return 1; // 1-1 > 1-sp + + case LIST_ITEM: + Iterator<Item> left = iterator(); + Iterator<Item> right = ( (ListItem) item ).iterator(); + + while ( left.hasNext() || right.hasNext() ) + { + Item l = left.hasNext() ? left.next() : null; + Item r = right.hasNext() ? right.next() : null; + + // if this is shorter, then invert the compare and mul with -1 + int result = l == null ? ( r == null ? 0 : -1 * r.compareTo( l ) ) : l.compareTo( r ); + + if ( result != 0 ) + { + return result; + } + } + + return 0; + + default: + throw new RuntimeException( "invalid item: " + item.getClass() ); + } + } + + public String toString() + { + StringBuilder buffer = new StringBuilder(); + for ( Iterator<Item> iter = iterator(); iter.hasNext(); ) + { + Item item = iter.next(); + if ( buffer.length() > 0 ) + { + buffer.append( ( item instanceof ListItem ) ? '-' : '.' ); + } + buffer.append( item ); + } + return buffer.toString(); + } + } + + public ComparableVersion( String version ) + { + parseVersion( version ); + } + + public final void parseVersion( String version ) + { + this.value = version; + + items = new ListItem(); + + version = version.toLowerCase( Locale.ENGLISH ); + + ListItem list = items; + + Stack<Item> stack = new Stack<Item>(); + stack.push( list ); + + boolean isDigit = false; + + int startIndex = 0; + + for ( int i = 0; i < version.length(); i++ ) + { + char c = version.charAt( i ); + + if ( c == '.' ) + { + if ( i == startIndex ) + { + list.add( IntegerItem.ZERO ); + } + else + { + list.add( parseItem( isDigit, version.substring( startIndex, i ) ) ); + } + startIndex = i + 1; + } + else if ( c == '-' ) + { + if ( i == startIndex ) + { + list.add( IntegerItem.ZERO ); + } + else + { + list.add( parseItem( isDigit, version.substring( startIndex, i ) ) ); + } + startIndex = i + 1; + + list.add( list = new ListItem() ); + stack.push( list ); + } + else if ( Character.isDigit( c ) ) + { + if ( !isDigit && i > startIndex ) + { + list.add( new StringItem( version.substring( startIndex, i ), true ) ); + startIndex = i; + + list.add( list = new ListItem() ); + stack.push( list ); + } + + isDigit = true; + } + else + { + if ( isDigit && i > startIndex ) + { + list.add( parseItem( true, version.substring( startIndex, i ) ) ); + startIndex = i; + + list.add( list = new ListItem() ); + stack.push( list ); + } + + isDigit = false; + } + } + + if ( version.length() > startIndex ) + { + list.add( parseItem( isDigit, version.substring( startIndex ) ) ); + } + + while ( !stack.isEmpty() ) + { + list = (ListItem) stack.pop(); + list.normalize(); + } + + canonical = items.toString(); + } + + private static Item parseItem( boolean isDigit, String buf ) + { + return isDigit ? new IntegerItem( buf ) : new StringItem( buf, false ); + } + + public int compareTo( ComparableVersion o ) + { + return items.compareTo( o.items ); + } + + public String toString() + { + return value; + } + + public String getCanonical() + { + return canonical; + } + + public boolean equals( Object o ) + { + return ( o instanceof ComparableVersion ) && canonical.equals( ( (ComparableVersion) o ).canonical ); + } + + public int hashCode() + { + return canonical.hashCode(); + } + + /** + * Main to test version parsing and comparison. + * + * @param args the version strings to parse and compare + */ + public static void main( String... args ) + { + System.out.println( "Display parameters as parsed by Maven (in canonical form) and comparison result:" ); + if ( args.length == 0 ) + { + return; + } + + ComparableVersion prev = null; + int i = 1; + for ( String version : args ) + { + ComparableVersion c = new ComparableVersion( version ); + + if ( prev != null ) + { + int compare = prev.compareTo( c ); + System.out.println( " " + prev.toString() + ' ' + + ( ( compare == 0 ) ? "==" : ( ( compare < 0 ) ? "<" : ">" ) ) + ' ' + version ); + } + + System.out.println( String.valueOf( i++ ) + ". " + version + " == " + c.getCanonical() ); + + prev = c; + } + } +} diff --git a/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/DefaultArtifactVersion.java b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/DefaultArtifactVersion.java new file mode 100644 index 00000000..99b2b85b --- /dev/null +++ b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/DefaultArtifactVersion.java @@ -0,0 +1,228 @@ +package org.apache.maven.artifact.versioning; + +/* + * 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.util.StringTokenizer; +import java.util.regex.Pattern; +import java.util.NoSuchElementException; + +/** + * Default implementation of artifact versioning. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + */ +public class DefaultArtifactVersion + implements ArtifactVersion +{ + private Integer majorVersion; + + private Integer minorVersion; + + private Integer incrementalVersion; + + private Integer buildNumber; + + private String qualifier; + + private ComparableVersion comparable; + + public DefaultArtifactVersion( String version ) + { + parseVersion( version ); + } + + @Override + public int hashCode() + { + return 11 + comparable.hashCode(); + } + + @Override + public boolean equals( Object other ) + { + if ( this == other ) + { + return true; + } + + if ( !( other instanceof ArtifactVersion ) ) + { + return false; + } + + return compareTo( (ArtifactVersion) other ) == 0; + } + + public int compareTo( ArtifactVersion otherVersion ) + { + if ( otherVersion instanceof DefaultArtifactVersion ) + { + return this.comparable.compareTo( ( (DefaultArtifactVersion) otherVersion ).comparable ); + } + else + { + return compareTo( new DefaultArtifactVersion( otherVersion.toString() ) ); + } + } + + public int getMajorVersion() + { + return majorVersion != null ? majorVersion : 0; + } + + public int getMinorVersion() + { + return minorVersion != null ? minorVersion : 0; + } + + public int getIncrementalVersion() + { + return incrementalVersion != null ? incrementalVersion : 0; + } + + public int getBuildNumber() + { + return buildNumber != null ? buildNumber : 0; + } + + public String getQualifier() + { + return qualifier; + } + + public final void parseVersion( String version ) + { + comparable = new ComparableVersion( version ); + + int index = version.indexOf( "-" ); + + String part1; + String part2 = null; + + if ( index < 0 ) + { + part1 = version; + } + else + { + part1 = version.substring( 0, index ); + part2 = version.substring( index + 1 ); + } + + if ( part2 != null ) + { + try + { + if ( ( part2.length() == 1 ) || !part2.startsWith( "0" ) ) + { + buildNumber = Integer.valueOf( part2 ); + } + else + { + qualifier = part2; + } + } + catch ( NumberFormatException e ) + { + qualifier = part2; + } + } + + if ( ( !part1.contains( "." ) ) && !part1.startsWith( "0" ) ) + { + try + { + majorVersion = Integer.valueOf( part1 ); + } + catch ( NumberFormatException e ) + { + // qualifier is the whole version, including "-" + qualifier = version; + buildNumber = null; + } + } + else + { + boolean fallback = false; + + StringTokenizer tok = new StringTokenizer( part1, "." ); + try + { + majorVersion = getNextIntegerToken( tok ); + if ( tok.hasMoreTokens() ) + { + minorVersion = getNextIntegerToken( tok ); + } + if ( tok.hasMoreTokens() ) + { + incrementalVersion = getNextIntegerToken( tok ); + } + if ( tok.hasMoreTokens() ) + { + qualifier = tok.nextToken(); + fallback = Pattern.compile( "\\d+" ).matcher( qualifier ).matches(); + } + + // string tokenzier won't detect these and ignores them + if ( part1.contains( ".." ) || part1.startsWith( "." ) || part1.endsWith( "." ) ) + { + fallback = true; + } + } + catch ( NumberFormatException e ) + { + fallback = true; + } + + if ( fallback ) + { + // qualifier is the whole version, including "-" + qualifier = version; + majorVersion = null; + minorVersion = null; + incrementalVersion = null; + buildNumber = null; + } + } + } + + private static Integer getNextIntegerToken( StringTokenizer tok ) + { + try + { + String s = tok.nextToken(); + if ( ( s.length() > 1 ) && s.startsWith( "0" ) ) + { + throw new NumberFormatException( "Number part has a leading 0: '" + s + "'" ); + } + return Integer.valueOf( s ); + } + catch ( NoSuchElementException e ) + { + throw new NumberFormatException( "Number is invalid" ); + } + } + + @Override + public String toString() + { + return comparable.toString(); + } +} diff --git a/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/InvalidVersionSpecificationException.java b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/InvalidVersionSpecificationException.java new file mode 100644 index 00000000..adc48b93 --- /dev/null +++ b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/InvalidVersionSpecificationException.java @@ -0,0 +1,34 @@ +package org.apache.maven.artifact.versioning; + +/* + * 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. + */ + +/** + * Occurs when a version is invalid. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + */ +public class InvalidVersionSpecificationException + extends Exception +{ + public InvalidVersionSpecificationException( String message ) + { + super( message ); + } +} diff --git a/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/OverConstrainedVersionException.java b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/OverConstrainedVersionException.java new file mode 100644 index 00000000..bd8f3830 --- /dev/null +++ b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/OverConstrainedVersionException.java @@ -0,0 +1,49 @@ +package org.apache.maven.artifact.versioning; + +/* + * 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.util.List; + +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.resolver.ArtifactResolutionException; + +/** + * Occurs when ranges exclude each other and no valid value remains. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + */ +public class OverConstrainedVersionException + extends ArtifactResolutionException +{ + public OverConstrainedVersionException( String msg, + Artifact artifact ) + { + super( msg, artifact ); + } + + public OverConstrainedVersionException( String msg, + Artifact artifact, + List<ArtifactRepository> remoteRepositories ) + { + super( msg, artifact, remoteRepositories ); + } + +} diff --git a/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/Restriction.java b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/Restriction.java new file mode 100644 index 00000000..d73d7ea5 --- /dev/null +++ b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/Restriction.java @@ -0,0 +1,195 @@ +package org.apache.maven.artifact.versioning; + +/* + * 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. + */ + +/** + * Describes a restriction in versioning. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + */ +public class Restriction +{ + private final ArtifactVersion lowerBound; + + private final boolean lowerBoundInclusive; + + private final ArtifactVersion upperBound; + + private final boolean upperBoundInclusive; + + public static final Restriction EVERYTHING = new Restriction( null, false, null, false ); + + public Restriction( ArtifactVersion lowerBound, boolean lowerBoundInclusive, ArtifactVersion upperBound, + boolean upperBoundInclusive ) + { + this.lowerBound = lowerBound; + this.lowerBoundInclusive = lowerBoundInclusive; + this.upperBound = upperBound; + this.upperBoundInclusive = upperBoundInclusive; + } + + public ArtifactVersion getLowerBound() + { + return lowerBound; + } + + public boolean isLowerBoundInclusive() + { + return lowerBoundInclusive; + } + + public ArtifactVersion getUpperBound() + { + return upperBound; + } + + public boolean isUpperBoundInclusive() + { + return upperBoundInclusive; + } + + public boolean containsVersion( ArtifactVersion version ) + { + if ( lowerBound != null ) + { + int comparison = lowerBound.compareTo( version ); + + if ( ( comparison == 0 ) && !lowerBoundInclusive ) + { + return false; + } + if ( comparison > 0 ) + { + return false; + } + } + if ( upperBound != null ) + { + int comparison = upperBound.compareTo( version ); + + if ( ( comparison == 0 ) && !upperBoundInclusive ) + { + return false; + } + if ( comparison < 0 ) + { + return false; + } + } + + return true; + } + + @Override + public int hashCode() + { + int result = 13; + + if ( lowerBound == null ) + { + result += 1; + } + else + { + result += lowerBound.hashCode(); + } + + result *= lowerBoundInclusive ? 1 : 2; + + if ( upperBound == null ) + { + result -= 3; + } + else + { + result -= upperBound.hashCode(); + } + + result *= upperBoundInclusive ? 2 : 3; + + return result; + } + + @Override + public boolean equals( Object other ) + { + if ( this == other ) + { + return true; + } + + if ( !( other instanceof Restriction ) ) + { + return false; + } + + Restriction restriction = (Restriction) other; + if ( lowerBound != null ) + { + if ( !lowerBound.equals( restriction.lowerBound ) ) + { + return false; + } + } + else if ( restriction.lowerBound != null ) + { + return false; + } + + if ( lowerBoundInclusive != restriction.lowerBoundInclusive ) + { + return false; + } + + if ( upperBound != null ) + { + if ( !upperBound.equals( restriction.upperBound ) ) + { + return false; + } + } + else if ( restriction.upperBound != null ) + { + return false; + } + + return upperBoundInclusive == restriction.upperBoundInclusive; + + } + + public String toString() + { + StringBuilder buf = new StringBuilder(); + + buf.append( isLowerBoundInclusive() ? "[" : "(" ); + if ( getLowerBound() != null ) + { + buf.append( getLowerBound().toString() ); + } + buf.append( "," ); + if ( getUpperBound() != null ) + { + buf.append( getUpperBound().toString() ); + } + buf.append( isUpperBoundInclusive() ? "]" : ")" ); + + return buf.toString(); + } +} diff --git a/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java new file mode 100644 index 00000000..dd8e028c --- /dev/null +++ b/framework/src/maven/apache-maven-3.3.3/maven-artifact/src/main/java/org/apache/maven/artifact/versioning/VersionRange.java @@ -0,0 +1,583 @@ +package org.apache.maven.artifact.versioning; + +/* + * 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.util.ArrayList; +import java.util.Collections; +import java.util.Iterator; +import java.util.List; + +import org.apache.maven.artifact.Artifact; + +/** + * Construct a version range from a specification. + * + * @author <a href="mailto:brett@apache.org">Brett Porter</a> + */ +public class VersionRange +{ + private final ArtifactVersion recommendedVersion; + + private final List<Restriction> restrictions; + + private VersionRange( ArtifactVersion recommendedVersion, + List<Restriction> restrictions ) + { + this.recommendedVersion = recommendedVersion; + this.restrictions = restrictions; + } + + public ArtifactVersion getRecommendedVersion() + { + return recommendedVersion; + } + + public List<Restriction> getRestrictions() + { + return restrictions; + } + + public VersionRange cloneOf() + { + List<Restriction> copiedRestrictions = null; + + if ( restrictions != null ) + { + copiedRestrictions = new ArrayList<Restriction>(); + + if ( !restrictions.isEmpty() ) + { + copiedRestrictions.addAll( restrictions ); + } + } + + return new VersionRange( recommendedVersion, copiedRestrictions ); + } + + /** + * Create a version range from a string representation + * <p/> + * Some spec examples are + * <ul> + * <li><code>1.0</code> Version 1.0</li> + * <li><code>[1.0,2.0)</code> Versions 1.0 (included) to 2.0 (not included)</li> + * <li><code>[1.0,2.0]</code> Versions 1.0 to 2.0 (both included)</li> + * <li><code>[1.5,)</code> Versions 1.5 and higher</li> + * <li><code>(,1.0],[1.2,)</code> Versions up to 1.0 (included) and 1.2 or higher</li> + * </ul> + * + * @param spec string representation of a version or version range + * @return a new {@link VersionRange} object that represents the spec + * @throws InvalidVersionSpecificationException + * + */ + public static VersionRange createFromVersionSpec( String spec ) + throws InvalidVersionSpecificationException + { + if ( spec == null ) + { + return null; + } + + List<Restriction> restrictions = new ArrayList<Restriction>(); + String process = spec; + ArtifactVersion version = null; + ArtifactVersion upperBound = null; + ArtifactVersion lowerBound = null; + + while ( process.startsWith( "[" ) || process.startsWith( "(" ) ) + { + int index1 = process.indexOf( ")" ); + int index2 = process.indexOf( "]" ); + + int index = index2; + if ( index2 < 0 || index1 < index2 ) + { + if ( index1 >= 0 ) + { + index = index1; + } + } + + if ( index < 0 ) + { + throw new InvalidVersionSpecificationException( "Unbounded range: " + spec ); + } + + Restriction restriction = parseRestriction( process.substring( 0, index + 1 ) ); + if ( lowerBound == null ) + { + lowerBound = restriction.getLowerBound(); + } + if ( upperBound != null ) + { + if ( restriction.getLowerBound() == null || restriction.getLowerBound().compareTo( upperBound ) < 0 ) + { + throw new InvalidVersionSpecificationException( "Ranges overlap: " + spec ); + } + } + restrictions.add( restriction ); + upperBound = restriction.getUpperBound(); + + process = process.substring( index + 1 ).trim(); + + if ( process.length() > 0 && process.startsWith( "," ) ) + { + process = process.substring( 1 ).trim(); + } + } + + if ( process.length() > 0 ) + { + if ( restrictions.size() > 0 ) + { + throw new InvalidVersionSpecificationException( + "Only fully-qualified sets allowed in multiple set scenario: " + spec ); + } + else + { + version = new DefaultArtifactVersion( process ); + restrictions.add( Restriction.EVERYTHING ); + } + } + + return new VersionRange( version, restrictions ); + } + + private static Restriction parseRestriction( String spec ) + throws InvalidVersionSpecificationException + { + boolean lowerBoundInclusive = spec.startsWith( "[" ); + boolean upperBoundInclusive = spec.endsWith( "]" ); + + String process = spec.substring( 1, spec.length() - 1 ).trim(); + + Restriction restriction; + + int index = process.indexOf( "," ); + + if ( index < 0 ) + { + if ( !lowerBoundInclusive || !upperBoundInclusive ) + { + throw new InvalidVersionSpecificationException( "Single version must be surrounded by []: " + spec ); + } + + ArtifactVersion version = new DefaultArtifactVersion( process ); + + restriction = new Restriction( version, lowerBoundInclusive, version, upperBoundInclusive ); + } + else + { + String lowerBound = process.substring( 0, index ).trim(); + String upperBound = process.substring( index + 1 ).trim(); + if ( lowerBound.equals( upperBound ) ) + { + throw new InvalidVersionSpecificationException( "Range cannot have identical boundaries: " + spec ); + } + + ArtifactVersion lowerVersion = null; + if ( lowerBound.length() > 0 ) + { + lowerVersion = new DefaultArtifactVersion( lowerBound ); + } + ArtifactVersion upperVersion = null; + if ( upperBound.length() > 0 ) + { + upperVersion = new DefaultArtifactVersion( upperBound ); + } + + if ( upperVersion != null && lowerVersion != null && upperVersion.compareTo( lowerVersion ) < 0 ) + { + throw new InvalidVersionSpecificationException( "Range defies version ordering: " + spec ); + } + + restriction = new Restriction( lowerVersion, lowerBoundInclusive, upperVersion, upperBoundInclusive ); + } + + return restriction; + } + + public static VersionRange createFromVersion( String version ) + { + List<Restriction> restrictions = Collections.emptyList(); + return new VersionRange( new DefaultArtifactVersion( version ), restrictions ); + } + + /** + * Creates and returns a new <code>VersionRange</code> that is a restriction of this + * version range and the specified version range. + * <p> + * Note: Precedence is given to the recommended version from this version range over the + * recommended version from the specified version range. + * </p> + * + * @param restriction the <code>VersionRange</code> that will be used to restrict this version + * range. + * @return the <code>VersionRange</code> that is a restriction of this version range and the + * specified version range. + * <p> + * The restrictions of the returned version range will be an intersection of the restrictions + * of this version range and the specified version range if both version ranges have + * restrictions. Otherwise, the restrictions on the returned range will be empty. + * </p> + * <p> + * The recommended version of the returned version range will be the recommended version of + * this version range, provided that ranges falls within the intersected restrictions. If + * the restrictions are empty, this version range's recommended version is used if it is not + * <code>null</code>. If it is <code>null</code>, the specified version range's recommended + * version is used (provided it is non-<code>null</code>). If no recommended version can be + * obtained, the returned version range's recommended version is set to <code>null</code>. + * </p> + * @throws NullPointerException if the specified <code>VersionRange</code> is + * <code>null</code>. + */ + public VersionRange restrict( VersionRange restriction ) + { + List<Restriction> r1 = this.restrictions; + List<Restriction> r2 = restriction.restrictions; + List<Restriction> restrictions; + + if ( r1.isEmpty() || r2.isEmpty() ) + { + restrictions = Collections.emptyList(); + } + else + { + restrictions = intersection( r1, r2 ); + } + + ArtifactVersion version = null; + if ( restrictions.size() > 0 ) + { + for ( Restriction r : restrictions ) + { + if ( recommendedVersion != null && r.containsVersion( recommendedVersion ) ) + { + // if we find the original, use that + version = recommendedVersion; + break; + } + else if ( version == null && restriction.getRecommendedVersion() != null + && r.containsVersion( restriction.getRecommendedVersion() ) ) + { + // use this if we can, but prefer the original if possible + version = restriction.getRecommendedVersion(); + } + } + } + // Either the original or the specified version ranges have no restrictions + else if ( recommendedVersion != null ) + { + // Use the original recommended version since it exists + version = recommendedVersion; + } + else if ( restriction.recommendedVersion != null ) + { + // Use the recommended version from the specified VersionRange since there is no + // original recommended version + version = restriction.recommendedVersion; + } +/* TODO: should throw this immediately, but need artifact + else + { + throw new OverConstrainedVersionException( "Restricting incompatible version ranges" ); + } +*/ + + return new VersionRange( version, restrictions ); + } + + private List<Restriction> intersection( List<Restriction> r1, List<Restriction> r2 ) + { + List<Restriction> restrictions = new ArrayList<Restriction>( r1.size() + r2.size() ); + Iterator<Restriction> i1 = r1.iterator(); + Iterator<Restriction> i2 = r2.iterator(); + Restriction res1 = i1.next(); + Restriction res2 = i2.next(); + + boolean done = false; + while ( !done ) + { + if ( res1.getLowerBound() == null || res2.getUpperBound() == null + || res1.getLowerBound().compareTo( res2.getUpperBound() ) <= 0 ) + { + if ( res1.getUpperBound() == null || res2.getLowerBound() == null + || res1.getUpperBound().compareTo( res2.getLowerBound() ) >= 0 ) + { + ArtifactVersion lower; + ArtifactVersion upper; + boolean lowerInclusive; + boolean upperInclusive; + + // overlaps + if ( res1.getLowerBound() == null ) + { + lower = res2.getLowerBound(); + lowerInclusive = res2.isLowerBoundInclusive(); + } + else if ( res2.getLowerBound() == null ) + { + lower = res1.getLowerBound(); + lowerInclusive = res1.isLowerBoundInclusive(); + } + else + { + int comparison = res1.getLowerBound().compareTo( res2.getLowerBound() ); + if ( comparison < 0 ) + { + lower = res2.getLowerBound(); + lowerInclusive = res2.isLowerBoundInclusive(); + } + else if ( comparison == 0 ) + { + lower = res1.getLowerBound(); + lowerInclusive = res1.isLowerBoundInclusive() && res2.isLowerBoundInclusive(); + } + else + { + lower = res1.getLowerBound(); + lowerInclusive = res1.isLowerBoundInclusive(); + } + } + + if ( res1.getUpperBound() == null ) + { + upper = res2.getUpperBound(); + upperInclusive = res2.isUpperBoundInclusive(); + } + else if ( res2.getUpperBound() == null ) + { + upper = res1.getUpperBound(); + upperInclusive = res1.isUpperBoundInclusive(); + } + else + { + int comparison = res1.getUpperBound().compareTo( res2.getUpperBound() ); + if ( comparison < 0 ) + { + upper = res1.getUpperBound(); + upperInclusive = res1.isUpperBoundInclusive(); + } + else if ( comparison == 0 ) + { + upper = res1.getUpperBound(); + upperInclusive = res1.isUpperBoundInclusive() && res2.isUpperBoundInclusive(); + } + else + { + upper = res2.getUpperBound(); + upperInclusive = res2.isUpperBoundInclusive(); + } + } + + // don't add if they are equal and one is not inclusive + if ( lower == null || upper == null || lower.compareTo( upper ) != 0 ) + { + restrictions.add( new Restriction( lower, lowerInclusive, upper, upperInclusive ) ); + } + else if ( lowerInclusive && upperInclusive ) + { + restrictions.add( new Restriction( lower, lowerInclusive, upper, upperInclusive ) ); + } + + //noinspection ObjectEquality + if ( upper == res2.getUpperBound() ) + { + // advance res2 + if ( i2.hasNext() ) + { + res2 = i2.next(); + } + else + { + done = true; + } + } + else + { + // advance res1 + if ( i1.hasNext() ) + { + res1 = i1.next(); + } + else + { + done = true; + } + } + } + else + { + // move on to next in r1 + if ( i1.hasNext() ) + { + res1 = i1.next(); + } + else + { + done = true; + } + } + } + else + { + // move on to next in r2 + if ( i2.hasNext() ) + { + res2 = i2.next(); + } + else + { + done = true; + } + } + } + + return restrictions; + } + + public ArtifactVersion getSelectedVersion( Artifact artifact ) + throws OverConstrainedVersionException + { + ArtifactVersion version; + if ( recommendedVersion != null ) + { + version = recommendedVersion; + } + else + { + if ( restrictions.size() == 0 ) + { + throw new OverConstrainedVersionException( "The artifact has no valid ranges", artifact ); + } + + version = null; + } + return version; + } + + public boolean isSelectedVersionKnown( Artifact artifact ) + throws OverConstrainedVersionException + { + boolean value = false; + if ( recommendedVersion != null ) + { + value = true; + } + else + { + if ( restrictions.size() == 0 ) + { + throw new OverConstrainedVersionException( "The artifact has no valid ranges", artifact ); + } + } + return value; + } + + public String toString() + { + if ( recommendedVersion != null ) + { + return recommendedVersion.toString(); + } + else + { + StringBuilder buf = new StringBuilder(); + for ( Iterator<Restriction> i = restrictions.iterator(); i.hasNext(); ) + { + Restriction r = i.next(); + + buf.append( r.toString() ); + + if ( i.hasNext() ) + { + buf.append( ',' ); + } + } + return buf.toString(); + } + } + + public ArtifactVersion matchVersion( List<ArtifactVersion> versions ) + { + // TODO: could be more efficient by sorting the list and then moving along the restrictions in order? + + ArtifactVersion matched = null; + for ( ArtifactVersion version : versions ) + { + if ( containsVersion( version ) ) + { + // valid - check if it is greater than the currently matched version + if ( matched == null || version.compareTo( matched ) > 0 ) + { + matched = version; + } + } + } + return matched; + } + + public boolean containsVersion( ArtifactVersion version ) + { + for ( Restriction restriction : restrictions ) + { + if ( restriction.containsVersion( version ) ) + { + return true; + } + } + return false; + } + + public boolean hasRestrictions() + { + return !restrictions.isEmpty() && recommendedVersion == null; + } + + public boolean equals( Object obj ) + { + if ( this == obj ) + { + return true; + } + if ( !( obj instanceof VersionRange ) ) + { + return false; + } + VersionRange other = (VersionRange) obj; + + boolean equals = + recommendedVersion == other.recommendedVersion + || ( ( recommendedVersion != null ) && recommendedVersion.equals( other.recommendedVersion ) ); + equals &= + restrictions == other.restrictions + || ( ( restrictions != null ) && restrictions.equals( other.restrictions ) ); + return equals; + } + + public int hashCode() + { + int hash = 7; + hash = 31 * hash + ( recommendedVersion == null ? 0 : recommendedVersion.hashCode() ); + hash = 31 * hash + ( restrictions == null ? 0 : restrictions.hashCode() ); + return hash; + } +} |