diff --git a/maven-resolver-api/pom.xml b/maven-resolver-api/pom.xml index f4129833e..bf6a1f3be 100644 --- a/maven-resolver-api/pom.xml +++ b/maven-resolver-api/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-api diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManagement.java b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManagement.java index 054bfe01b..42ecc2585 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManagement.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManagement.java @@ -27,7 +27,7 @@ /** * The management updates to apply to a dependency. - * + * * @see DependencyManager#manageDependency(Dependency) */ public final class DependencyManagement @@ -35,27 +35,53 @@ public final class DependencyManagement private String version; + /** + * @since 1.2.0 + */ + private String versionSourceHint; + private String scope; + /** + * @since 1.2.0 + */ + private String scopeSourceHint; + private Boolean optional; + /** + * @since 1.2.0 + */ + private String optionalSourceHint; + private Collection exclusions; + /** + * @since 1.2.0 + */ + private String exclusionsSourceHint; + private Map properties; + /** + * @since 1.2.0 + */ + private String propertiesSourceHint; + /** * Creates an empty management update. */ public DependencyManagement() { // enables default constructor + super(); } /** * Gets the new version to apply to the dependency. - * + * * @return The new version or {@code null} if the version is not managed and the existing dependency version should - * remain unchanged. + * remain unchanged. */ public String getVersion() { @@ -64,7 +90,7 @@ public String getVersion() /** * Sets the new version to apply to the dependency. - * + * * @param version The new version, may be {@code null} if the version is not managed. * @return This management update for chaining, never {@code null}. */ @@ -74,11 +100,33 @@ public DependencyManagement setVersion( String version ) return this; } + /** + * Gets an informational hint describing the source declaring the version management. + * @return An informational hint describing the source declaring the version management or {@code null}. + * @since 1.2.0 + */ + public String getVersionSourceHint() + { + return this.versionSourceHint; + } + + /** + * Sets the informational hint describing the source declaring the version management. + * @param value The new informational hint decsribing the source declaring the version management or {@code null}. + * @return This management update for chaining, never {@code null}. + * @since 1.2.0 + */ + public DependencyManagement setVersionSourceHint( final String value ) + { + this.versionSourceHint = value; + return this; + } + /** * Gets the new scope to apply to the dependency. - * + * * @return The new scope or {@code null} if the scope is not managed and the existing dependency scope should remain - * unchanged. + * unchanged. */ public String getScope() { @@ -87,7 +135,7 @@ public String getScope() /** * Sets the new scope to apply to the dependency. - * + * * @param scope The new scope, may be {@code null} if the scope is not managed. * @return This management update for chaining, never {@code null}. */ @@ -97,11 +145,33 @@ public DependencyManagement setScope( String scope ) return this; } + /** + * Gets an informational hint describing the source declaring the scope management. + * @return An informational hint describing the source declaring the scope management or {@code null}. + * @since 1.2.0 + */ + public String getScopeSourceHint() + { + return this.scopeSourceHint; + } + + /** + * Sets the informational hint describing the source declaring the scope management. + * @param value The new informational hint decsribing the source declaring the scope management or {@code null}. + * @return This management update for chaining, never {@code null}. + * @since 1.2.0 + */ + public DependencyManagement setScopeSourceHint( final String value ) + { + this.scopeSourceHint = value; + return this; + } + /** * Gets the new optional flag to apply to the dependency. - * + * * @return The new optional flag or {@code null} if the flag is not managed and the existing optional flag of the - * dependency should remain unchanged. + * dependency should remain unchanged. */ public Boolean getOptional() { @@ -110,7 +180,7 @@ public Boolean getOptional() /** * Sets the new optional flag to apply to the dependency. - * + * * @param optional The optional flag, may be {@code null} if the flag is not managed. * @return This management update for chaining, never {@code null}. */ @@ -120,13 +190,36 @@ public DependencyManagement setOptional( Boolean optional ) return this; } + /** + * Gets an informational hint describing the source declaring the optionality management. + * @return An informational hint describing the source declaring the optionality management or {@code null}. + * @since 1.2.0 + */ + public String getOptionalitySourceHint() + { + return this.optionalSourceHint; + } + + /** + * Sets the informational hint describing the source declaring the optionality management. + * @param value The new informational hint decsribing the source declaring the optionality management or + * {@code null}. + * @return This management update for chaining, never {@code null}. + * @since 1.2.0 + */ + public DependencyManagement setOptionalitySourceHint( final String value ) + { + this.optionalSourceHint = value; + return this; + } + /** * Gets the new exclusions to apply to the dependency. Note that this collection denotes the complete set of * exclusions for the dependency, i.e. the dependency manager controls whether any existing exclusions get merged * with information from dependency management or overridden by it. - * + * * @return The new exclusions or {@code null} if the exclusions are not managed and the existing dependency - * exclusions should remain unchanged. + * exclusions should remain unchanged. */ public Collection getExclusions() { @@ -137,7 +230,7 @@ public Collection getExclusions() * Sets the new exclusions to apply to the dependency. Note that this collection denotes the complete set of * exclusions for the dependency, i.e. the dependency manager controls whether any existing exclusions get merged * with information from dependency management or overridden by it. - * + * * @param exclusions The new exclusions, may be {@code null} if the exclusions are not managed. * @return This management update for chaining, never {@code null}. */ @@ -147,13 +240,36 @@ public DependencyManagement setExclusions( Collection exclusions ) return this; } + /** + * Gets an informational hint describing the source declaring the exclusions management. + * @return An informational hint describing the source declaring the exclusions management or {@code null}. + * @since 1.2.0 + */ + public String getExclusionsSourceHint() + { + return this.exclusionsSourceHint; + } + + /** + * Sets the informational hint describing the source declaring the exclusions management. + * @param value The new informational hint decsribing the source declaring the exclusions management or + * {@code null}. + * @return This management update for chaining, never {@code null}. + * @since 1.2.0 + */ + public DependencyManagement setExclusionsSourceHint( final String value ) + { + this.exclusionsSourceHint = value; + return this; + } + /** * Gets the new properties to apply to the dependency. Note that this map denotes the complete set of properties, * i.e. the dependency manager controls whether any existing properties get merged with the information from * dependency management or overridden by it. - * + * * @return The new artifact properties or {@code null} if the properties are not managed and the existing properties - * should remain unchanged. + * should remain unchanged. */ public Map getProperties() { @@ -164,7 +280,7 @@ public Map getProperties() * Sets the new properties to apply to the dependency. Note that this map denotes the complete set of properties, * i.e. the dependency manager controls whether any existing properties get merged with the information from * dependency management or overridden by it. - * + * * @param properties The new artifact properties, may be {@code null} if the properties are not managed. * @return This management update for chaining, never {@code null}. */ @@ -174,4 +290,27 @@ public DependencyManagement setProperties( Map properties ) return this; } + /** + * Gets an informational hint describing the source declaring the properties management. + * @return An informational hint describing the source declaring the properties management or {@code null}. + * @since 1.2.0 + */ + public String getPropertiesSourceHint() + { + return this.propertiesSourceHint; + } + + /** + * Sets the informational hint describing the source declaring the properties management. + * @param value The new informational hint decsribing the source declaring the properties management or + * {@code null}. + * @return This management update for chaining, never {@code null}. + * @since 1.2.0 + */ + public DependencyManagement setPropertiesSourceHint( final String value ) + { + this.propertiesSourceHint = value; + return this; + } + } diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java index 2e1a78b6f..d4861c94d 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/Dependency.java @@ -45,9 +45,14 @@ public final class Dependency private final Set exclusions; + /** + * @since 1.2.0 + */ + private final String sourceHint; + /** * Creates a mandatory dependency on the specified artifact with the given scope. - * + * * @param artifact The artifact being depended on, must not be {@code null}. * @param scope The scope of the dependency, may be {@code null}. */ @@ -58,7 +63,7 @@ public Dependency( Artifact artifact, String scope ) /** * Creates a dependency on the specified artifact with the given scope. - * + * * @param artifact The artifact being depended on, must not be {@code null}. * @param scope The scope of the dependency, may be {@code null}. * @param optional A flag whether the dependency is optional or mandatory, may be {@code null}. @@ -70,7 +75,7 @@ public Dependency( Artifact artifact, String scope, Boolean optional ) /** * Creates a dependency on the specified artifact with the given scope and exclusions. - * + * * @param artifact The artifact being depended on, must not be {@code null}. * @param scope The scope of the dependency, may be {@code null}. * @param optional A flag whether the dependency is optional or mandatory, may be {@code null}. @@ -78,21 +83,65 @@ public Dependency( Artifact artifact, String scope, Boolean optional ) */ public Dependency( Artifact artifact, String scope, Boolean optional, Collection exclusions ) { - this( artifact, scope, Exclusions.copy( exclusions ), optional ); + this( null, artifact, scope, Exclusions.copy( exclusions ), optional ); + } + + /** + * Creates a dependency on the specified artifact. + * + * @param sourceHint An informational hint describing the source declaring the dependency, may be {@code null}. + * @param artifact The artifact being depended on, must not be {@code null}. + * @param scope The scope of the dependency, may be {@code null}. + * @param optional A flag whether the dependency is optional or mandatory, may be {@code null}. + * @param exclusions The exclusions that apply to transitive dependencies, may be {@code null} if none. + * @since 1.2.0 + */ + public Dependency( String sourceHint, Artifact artifact, String scope, Boolean optional, + Collection exclusions ) + { + this( sourceHint, artifact, scope, Exclusions.copy( exclusions ), optional ); } - private Dependency( Artifact artifact, String scope, Set exclusions, Boolean optional ) + private Dependency( String sourceHint, Artifact artifact, String scope, Set exclusions, + Boolean optional ) { // NOTE: This constructor assumes immutability of the provided exclusion collection, for internal use only this.artifact = requireNonNull( artifact, "artifact cannot be null" ); this.scope = ( scope != null ) ? scope : ""; this.optional = optional; this.exclusions = exclusions; + this.sourceHint = sourceHint; + } + + /** + * Gets an informational hint describing the source declaring the dependency. + * + * @return An informational hint describing the source declaring the dependency or {@code null}. + * @since 1.2.0 + */ + public String getSourceHint() + { + return this.sourceHint; + } + + /** + * Sets the informational hint describing the source declaring the dependency. + * @param value The new informational hint describing the source declaring the dependency or {@code null}. + * @return The new dependency, never {@code null}. + * @since 1.2.0 + */ + public Dependency setSourceHint( final String value ) + { + return ( this.sourceHint != null && this.sourceHint.equals( value ) ) + || ( this.sourceHint == value ) + ? this + : new Dependency( value, artifact, scope, exclusions, optional ); + } /** * Gets the artifact being depended on. - * + * * @return The artifact, never {@code null}. */ public Artifact getArtifact() @@ -102,7 +151,7 @@ public Artifact getArtifact() /** * Sets the artifact being depended on. - * + * * @param artifact The artifact, must not be {@code null}. * @return The new dependency, never {@code null}. */ @@ -112,12 +161,12 @@ public Dependency setArtifact( Artifact artifact ) { return this; } - return new Dependency( artifact, scope, exclusions, optional ); + return new Dependency( sourceHint, artifact, scope, exclusions, optional ); } /** * Gets the scope of the dependency. The scope defines in which context this dependency is relevant. - * + * * @return The scope or an empty string if not set, never {@code null}. */ public String getScope() @@ -127,7 +176,7 @@ public String getScope() /** * Sets the scope of the dependency, e.g. "compile". - * + * * @param scope The scope of the dependency, may be {@code null}. * @return The new dependency, never {@code null}. */ @@ -137,12 +186,12 @@ public Dependency setScope( String scope ) { return this; } - return new Dependency( artifact, scope, exclusions, optional ); + return new Dependency( sourceHint, artifact, scope, exclusions, optional ); } /** * Indicates whether this dependency is optional or not. Optional dependencies can be ignored in some contexts. - * + * * @return {@code true} if the dependency is (definitively) optional, {@code false} otherwise. */ public boolean isOptional() @@ -153,7 +202,7 @@ public boolean isOptional() /** * Gets the optional flag for the dependency. Note: Most clients will usually call {@link #isOptional()} to * determine the optional flag, this method is for advanced use cases where three-valued logic is required. - * + * * @return The optional flag or {@code null} if unspecified. */ public Boolean getOptional() @@ -163,9 +212,9 @@ public Boolean getOptional() /** * Sets the optional flag for the dependency. - * + * * @param optional {@code true} if the dependency is optional, {@code false} if the dependency is mandatory, may be - * {@code null} if unspecified. + * {@code null} if unspecified. * @return The new dependency, never {@code null}. */ public Dependency setOptional( Boolean optional ) @@ -174,13 +223,13 @@ public Dependency setOptional( Boolean optional ) { return this; } - return new Dependency( artifact, scope, exclusions, optional ); + return new Dependency( sourceHint, artifact, scope, exclusions, optional ); } /** * Gets the exclusions for this dependency. Exclusions can be used to remove transitive dependencies during * resolution. - * + * * @return The (read-only) exclusions, never {@code null}. */ public Collection getExclusions() @@ -190,7 +239,7 @@ public Collection getExclusions() /** * Sets the exclusions for the dependency. - * + * * @param exclusions The exclusions, may be {@code null}. * @return The new dependency, never {@code null}. */ @@ -200,7 +249,7 @@ public Dependency setExclusions( Collection exclusions ) { return this; } - return new Dependency( artifact, scope, optional, exclusions ); + return new Dependency( sourceHint, artifact, scope, optional, exclusions ); } private boolean hasEquivalentExclusions( Collection exclusions ) @@ -214,7 +263,7 @@ private boolean hasEquivalentExclusions( Collection exclusions ) return this.exclusions.equals( exclusions ); } return exclusions.size() >= this.exclusions.size() && this.exclusions.containsAll( exclusions ) - && exclusions.containsAll( this.exclusions ); + && exclusions.containsAll( this.exclusions ); } @Override @@ -238,7 +287,7 @@ else if ( obj == null || !getClass().equals( obj.getClass() ) ) Dependency that = (Dependency) obj; return artifact.equals( that.artifact ) && scope.equals( that.scope ) && eq( optional, that.optional ) - && exclusions.equals( that.exclusions ); + && exclusions.equals( that.exclusions ); } private static boolean eq( T o1, T o2 ) @@ -278,7 +327,7 @@ private Exclusions( Collection exclusions ) { exclusions = new LinkedHashSet( exclusions ); } - this.exclusions = exclusions.toArray( new Exclusion[exclusions.size()] ); + this.exclusions = exclusions.toArray( new Exclusion[ exclusions.size() ] ); } @Override diff --git a/maven-resolver-connector-basic/pom.xml b/maven-resolver-connector-basic/pom.xml index 0e896bc8f..0ccdafbcd 100644 --- a/maven-resolver-connector-basic/pom.xml +++ b/maven-resolver-connector-basic/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-connector-basic diff --git a/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml b/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml index 1b5c0700d..44a209322 100644 --- a/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml +++ b/maven-resolver-demos/maven-resolver-demo-maven-plugin/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver-demos - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-demo-maven-plugin diff --git a/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml b/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml index 99a115036..474d67e6b 100644 --- a/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml +++ b/maven-resolver-demos/maven-resolver-demo-snippets/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver-demos - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-demo-snippets diff --git a/maven-resolver-demos/pom.xml b/maven-resolver-demos/pom.xml index 0a9ed508a..dc3abcbf6 100644 --- a/maven-resolver-demos/pom.xml +++ b/maven-resolver-demos/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-demos diff --git a/maven-resolver-impl/pom.xml b/maven-resolver-impl/pom.xml index ddfa9fc04..7d820d417 100644 --- a/maven-resolver-impl/pom.xml +++ b/maven-resolver-impl/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-impl diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java index d2ca7d43f..686de1f8f 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollector.java @@ -8,9 +8,9 @@ * 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 @@ -115,7 +115,8 @@ public void initService( ServiceLocator locator ) public DefaultDependencyCollector setRemoteRepositoryManager( RemoteRepositoryManager remoteRepositoryManager ) { - this.remoteRepositoryManager = requireNonNull( remoteRepositoryManager, "remote repository provider cannot be null" ); + this.remoteRepositoryManager = requireNonNull( remoteRepositoryManager, + "remote repository provider cannot be null" ); return this; } @@ -362,16 +363,16 @@ private void processDependency( Args args, Results results, List relocations, boolean disableVersionManagement ) { + PremanagedDependency preManaged = + PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState ); + + dependency = preManaged.managedDependency; if ( depSelector != null && !depSelector.selectDependency( dependency ) ) { return; } - PremanagedDependency preManaged = - PremanagedDependency.create( depManager, dependency, disableVersionManagement, args.premanagedState ); - dependency = preManaged.managedDependency; - boolean noDescriptor = isLackingDescriptor( dependency.getArtifact() ); boolean traverse = !noDescriptor && ( depTraverser == null || depTraverser.traverseDependency( dependency ) ); @@ -572,6 +573,7 @@ private static DefaultDependencyNode createDependencyNode( List reloca DefaultDependencyNode child = createDependencyNode( relocations, preManaged, rangeResult, version, d, descriptorResult.getAliases(), cycleNode.getRepositories(), cycleNode.getRequestContext() ); + child.setChildren( cycleNode.getChildren() ); return child; } @@ -695,8 +697,8 @@ static class Args final CollectRequest request; Args( RepositorySystemSession session, RequestTrace trace, DataPool pool, NodeStack nodes, - DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext, - CollectRequest request ) + DefaultDependencyCollectionContext collectionContext, DefaultVersionFilterContext versionContext, + CollectRequest request ) { this.session = session; this.request = request; @@ -774,43 +776,77 @@ static class PremanagedDependency final String premanagedVersion; + /** + * @since 1.2.0 + */ + final String versionManagementSourceHint; + final String premanagedScope; + /** + * @since 1.2.0 + */ + final String scopeManagementSourceHint; + final Boolean premanagedOptional; + /** + * @since 1.2.0 + */ + final String optionalityManagementSourceHint; + /** * @since 1.1.0 */ final Collection premanagedExclusions; + /** + * @since 1.2.0 + */ + final String exclusionsManagementSourceHint; + /** * @since 1.1.0 */ final Map premanagedProperties; + /** + * @since 1.2.0 + */ + final String propertiesManagementSourceHint; + final int managedBits; final Dependency managedDependency; final boolean premanagedState; - PremanagedDependency( String premanagedVersion, String premanagedScope, Boolean premanagedOptional, - Collection premanagedExclusions, Map premanagedProperties, + PremanagedDependency( String premanagedVersion, String versionManagementSourceHint, + String premanagedScope, String scopeManagementSourceHint, + Boolean premanagedOptional, String optionalityManagementSourceHint, + Collection premanagedExclusions, String exclusionsManagementSourceHint, + Map premanagedProperties, String propertiesManagementSourceHint, int managedBits, Dependency managedDependency, boolean premanagedState ) { this.premanagedVersion = premanagedVersion; + this.versionManagementSourceHint = versionManagementSourceHint; this.premanagedScope = premanagedScope; + this.scopeManagementSourceHint = scopeManagementSourceHint; this.premanagedOptional = premanagedOptional; + this.optionalityManagementSourceHint = optionalityManagementSourceHint; this.premanagedExclusions = premanagedExclusions != null ? Collections.unmodifiableCollection( new ArrayList( premanagedExclusions ) ) : null; + this.exclusionsManagementSourceHint = exclusionsManagementSourceHint; + this.premanagedProperties = premanagedProperties != null ? Collections.unmodifiableMap( new HashMap( premanagedProperties ) ) : null; + this.propertiesManagementSourceHint = propertiesManagementSourceHint; this.managedBits = managedBits; this.managedDependency = managedDependency; this.premanagedState = premanagedState; @@ -823,10 +859,15 @@ static PremanagedDependency create( DependencyManager depManager, Dependency dep int managedBits = 0; String premanagedVersion = null; + String versionSourceHint = null; String premanagedScope = null; + String scopeSourceHint = null; Boolean premanagedOptional = null; + String optionalitySourceHint = null; Collection premanagedExclusions = null; + String exclusionsSourceHint = null; Map premanagedProperties = null; + String propertiesSourceHint = null; if ( depMngt != null ) { @@ -834,6 +875,7 @@ static PremanagedDependency create( DependencyManager depManager, Dependency dep { Artifact artifact = dependency.getArtifact(); premanagedVersion = artifact.getVersion(); + versionSourceHint = depMngt.getVersionSourceHint(); dependency = dependency.setArtifact( artifact.setVersion( depMngt.getVersion() ) ); managedBits |= DependencyNode.MANAGED_VERSION; } @@ -841,30 +883,38 @@ static PremanagedDependency create( DependencyManager depManager, Dependency dep { Artifact artifact = dependency.getArtifact(); premanagedProperties = artifact.getProperties(); + propertiesSourceHint = depMngt.getPropertiesSourceHint(); dependency = dependency.setArtifact( artifact.setProperties( depMngt.getProperties() ) ); managedBits |= DependencyNode.MANAGED_PROPERTIES; } if ( depMngt.getScope() != null ) { premanagedScope = dependency.getScope(); + scopeSourceHint = depMngt.getScopeSourceHint(); dependency = dependency.setScope( depMngt.getScope() ); managedBits |= DependencyNode.MANAGED_SCOPE; } if ( depMngt.getOptional() != null ) { premanagedOptional = dependency.isOptional(); + optionalitySourceHint = depMngt.getOptionalitySourceHint(); dependency = dependency.setOptional( depMngt.getOptional() ); managedBits |= DependencyNode.MANAGED_OPTIONAL; } if ( depMngt.getExclusions() != null ) { premanagedExclusions = dependency.getExclusions(); + exclusionsSourceHint = depMngt.getExclusionsSourceHint(); dependency = dependency.setExclusions( depMngt.getExclusions() ); managedBits |= DependencyNode.MANAGED_EXCLUSIONS; } } - return new PremanagedDependency( premanagedVersion, premanagedScope, premanagedOptional, - premanagedExclusions, premanagedProperties, managedBits, dependency, + return new PremanagedDependency( premanagedVersion, versionSourceHint, + premanagedScope, scopeSourceHint, + premanagedOptional, optionalitySourceHint, + premanagedExclusions, exclusionsSourceHint, + premanagedProperties, propertiesSourceHint, + managedBits, dependency, premanagedState ); } @@ -875,10 +925,25 @@ public void applyTo( DefaultDependencyNode child ) if ( premanagedState ) { child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION, premanagedVersion ); + child.setData( DependencyManagerUtils.NODE_DATA_VERSION_MANAGEMENT_SOURCE_HINT, + versionManagementSourceHint ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_SCOPE, premanagedScope ); + child.setData( DependencyManagerUtils.NODE_DATA_SCOPE_MANAGEMENT_SOURCE_HINT, + scopeManagementSourceHint ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_OPTIONAL, premanagedOptional ); + child.setData( DependencyManagerUtils.NODE_DATA_OPTIONALITY_MANAGEMENT_SOURCE_HINT, + optionalityManagementSourceHint ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_EXCLUSIONS, premanagedExclusions ); + child.setData( DependencyManagerUtils.NODE_DATA_EXCLUSIONS_MANAGEMENT_SOURCE_HINT, + exclusionsManagementSourceHint ); + child.setData( DependencyManagerUtils.NODE_DATA_PREMANAGED_PROPERTIES, premanagedProperties ); + child.setData( DependencyManagerUtils.NODE_DATA_PROPERTIES_MANAGEMENT_SOURCE_HINT, + propertiesManagementSourceHint ); + } } diff --git a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java index 0e2d6443f..94f9d0f9f 100644 --- a/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java +++ b/maven-resolver-impl/src/test/java/org/eclipse/aether/internal/impl/collect/DefaultDependencyCollectorTest.java @@ -43,6 +43,8 @@ import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.collection.DependencyManagement; import org.eclipse.aether.collection.DependencyManager; +import org.eclipse.aether.collection.DependencySelector; +import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyCycle; import org.eclipse.aether.graph.DependencyNode; @@ -59,7 +61,11 @@ import org.eclipse.aether.resolution.ArtifactDescriptorResult; import org.eclipse.aether.util.artifact.ArtifactIdUtils; import org.eclipse.aether.util.graph.manager.ClassicDependencyManager; +import org.eclipse.aether.util.graph.manager.DefaultDependencyManager; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.manager.TransitiveDependencyManager; +import org.eclipse.aether.util.graph.selector.OptionalDependencySelector; +import org.eclipse.aether.util.graph.selector.ScopeDependencySelector; import org.eclipse.aether.util.graph.version.HighestVersionFilter; import org.junit.Before; import org.junit.Test; @@ -386,6 +392,7 @@ public void testArtifactDescriptorResolutionNotRestrictedToRepoHostingSelectedVe collector.setArtifactDescriptorReader( new ArtifactDescriptorReader() { + public ArtifactDescriptorResult readArtifactDescriptor( RepositorySystemSession session, ArtifactDescriptorRequest request ) throws ArtifactDescriptorException @@ -393,6 +400,7 @@ public ArtifactDescriptorResult readArtifactDescriptor( RepositorySystemSession repos.addAll( request.getRepositories() ); return new ArtifactDescriptorResult( request ); } + } ); List dependencies = Arrays.asList( newDep( "verrange:parent:jar:1[1,)", "compile" ) ); @@ -482,6 +490,199 @@ public void testDependencyManagement_VerboseMode() assertEquals( Boolean.FALSE, DependencyManagerUtils.getPremanagedOptional( node ) ); } + @Test + public void testDependencyManagement_TransitiveDependencyManager() + throws DependencyCollectionException, IOException + { + collector.setArtifactDescriptorReader( newReader( "managed/" ) ); + parser = new DependencyGraphParser( "artifact-descriptions/managed/" ); + session.setDependencyManager( new TransitiveDependencyManager() ); + final Dependency root = newDep( "gid:root:ext:ver", "compile" ); + CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) ); + request.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) ); + CollectResult result = collector.collectDependencies( session, request ); + + final DependencyNode expectedTree = parser.parseResource( "management-tree.txt" ); + assertEqualSubtree( expectedTree, result.getRoot() ); + + // Same test for root artifact (POM) request. + final CollectRequest rootArtifactRequest = new CollectRequest(); + rootArtifactRequest.setRepositories( Arrays.asList( repository ) ); + rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) ); + rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "compile" ) ); + rootArtifactRequest.addManagedDependency( newDep( "gid:root:ext:must-retain-core-management" ) ); + rootArtifactRequest.addManagedDependency( newDep( "gid:direct:ext:must-retain-core-management" ) ); + rootArtifactRequest.addManagedDependency( newDep( "gid:transitive-1:ext:managed-by-root" ) ); + session.setDependencyManager( new TransitiveDependencyManager() ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertEqualSubtree( expectedTree, this.toDependencyResult( result.getRoot(), "compile", null ) ); + } + + @Test + public void testDependencyManagement_DefaultDependencyManager() + throws DependencyCollectionException, IOException + { + collector.setArtifactDescriptorReader( newReader( "managed/" ) ); + parser = new DependencyGraphParser( "artifact-descriptions/managed/" ); + session.setDependencyManager( new DefaultDependencyManager() ); + final Dependency root = newDep( "gid:root:ext:ver", "compile" ); + CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) ); + request.addManagedDependency( newDep( "gid:root:ext:must-not-manage-root" ) ); + request.addManagedDependency( newDep( "gid:direct:ext:managed-by-dominant-request" ) ); + CollectResult result = collector.collectDependencies( session, request ); + + final DependencyNode expectedTree = parser.parseResource( "default-management-tree.txt" ); + assertEqualSubtree( expectedTree, result.getRoot() ); + + // Same test for root artifact (POM) request. + final CollectRequest rootArtifactRequest = new CollectRequest(); + rootArtifactRequest.setRepositories( Arrays.asList( repository ) ); + rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) ); + rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "compile" ) ); + rootArtifactRequest.addManagedDependency( newDep( "gid:root:ext:must-not-manage-root" ) ); + rootArtifactRequest.addManagedDependency( newDep( "gid:direct:ext:managed-by-dominant-request" ) ); + rootArtifactRequest.addManagedDependency( newDep( "gid:transitive-1:ext:managed-by-root" ) ); + session.setDependencyManager( new DefaultDependencyManager() ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertEqualSubtree( expectedTree, this.toDependencyResult( result.getRoot(), "compile", null ) ); + } + + @Test + public void testDependencyManagement_DependencySelectorProcessesManagedState() + throws DependencyCollectionException, IOException + { + collector.setArtifactDescriptorReader( newReader( "selection/managed/" ) ); + parser = new DependencyGraphParser( "artifact-descriptions/selection/managed/" ); + + final Dependency root = newDep( "gid:root:ext:ver", "root-scope" ); + CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) ); + CollectResult result = collector.collectDependencies( session, request ); + + DependencyNode expected = parser.parseResource( "all-nodes.txt" ); + assertEqualSubtree( expected, result.getRoot() ); + + this.session.setDependencySelector( new DependencySelector() + { + + public boolean selectDependency( final Dependency dependency ) + { + return dependency != null + && !( "managed".equals( dependency.getScope() ) + || "managed".equals( dependency.getArtifact().getVersion() ) + || dependency.isOptional() ); + + } + + public DependencySelector deriveChildSelector( final DependencyCollectionContext context ) + { + return this; + } + + } ); + + // Tests managed scope is processed by selector. + TestDependencyManager depMgmt = new TestDependencyManager(); + depMgmt.scope( "gid:transitive-of-transitive-of-root:ext", "managed" ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "transitive-of-transitive-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + depMgmt = new TestDependencyManager(); + depMgmt.scope( "gid:transitive-of-root:ext", "managed" ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "transitive-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + depMgmt = new TestDependencyManager(); + depMgmt.scope( "gid:direct-of-root:ext", "managed" ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "direct-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + // Tests managed optionality is processed by selector. + depMgmt = new TestDependencyManager(); + depMgmt.optional( "gid:transitive-of-transitive-of-root:ext", Boolean.TRUE ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "transitive-of-transitive-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + depMgmt = new TestDependencyManager(); + depMgmt.optional( "gid:transitive-of-root:ext", Boolean.TRUE ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "transitive-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + depMgmt = new TestDependencyManager(); + depMgmt.optional( "gid:direct-of-root:ext", Boolean.TRUE ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "direct-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + // Tests managed version is processed by selector. + depMgmt = new TestDependencyManager(); + depMgmt.version( "gid:transitive-of-transitive-of-root:ext", "managed" ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "transitive-of-transitive-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + depMgmt = new TestDependencyManager(); + depMgmt.version( "gid:transitive-of-root:ext", "managed" ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "transitive-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + + depMgmt = new TestDependencyManager(); + depMgmt.version( "gid:direct-of-root:ext", "managed" ); + session.setDependencyManager( depMgmt ); + + expected = parser.parseResource( "direct-of-root.txt" ); + + request = new CollectRequest( root, Arrays.asList( repository ) ); + result = collector.collectDependencies( session, request ); + + assertEqualSubtree( expected, result.getRoot() ); + } + @Test public void testVersionFilter() throws Exception @@ -492,6 +693,151 @@ public void testVersionFilter() assertEquals( 1, result.getRoot().getChildren().size() ); } + @Test + public void testSelectionWithScopeDependencySelector() + throws DependencyCollectionException, IOException + { + collector.setArtifactDescriptorReader( newReader( "selection/scope/" ) ); + parser = new DependencyGraphParser( "artifact-descriptions/selection/scope/" ); + session.setDependencySelector( null ); + + final DependencyNode allNodes = parser.parseResource( "all-nodes.txt" ); + final DependencyNode transitive1ExclusionTree = parser.parseResource( "transitive-1-exclusion-tree.txt" ); + final DependencyNode transitive2ExclusionTree = parser.parseResource( "transitive-2-exclusion-tree.txt" ); + final Dependency root = newDep( "gid:root:ext:ver", "root-scope" ); + final CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) ); + CollectResult result = collector.collectDependencies( session, request ); + assertEqualSubtree( allNodes, result.getRoot() ); + + /* + A dependency selector that filters transitive dependencies based on their scope. Direct dependencies are always + included regardless of their scope. + */ + // Include all. + this.session.setDependencySelector( new ScopeDependencySelector() ); + result = collector.collectDependencies( session, request ); + assertEqualSubtree( allNodes, result.getRoot() ); + + // Exclude root scope equals include all as the root is always included. + this.session.setDependencySelector( new ScopeDependencySelector( "root-scope" ) ); + result = collector.collectDependencies( session, request ); + assertEqualSubtree( allNodes, result.getRoot() ); + + // Exclude direct scope equals include all as direct dependencies are always included. + this.session.setDependencySelector( new ScopeDependencySelector( "direct-scope" ) ); + result = collector.collectDependencies( session, request ); + assertEqualSubtree( allNodes, result.getRoot() ); + + // Exclude scope of transitive of direct. + this.session.setDependencySelector( new ScopeDependencySelector( "transitive-1-scope" ) ); + result = collector.collectDependencies( session, request ); + assertEqualSubtree( transitive1ExclusionTree, result.getRoot() ); + + // Exclude scope of transitive of transitive of direct dependency. + this.session.setDependencySelector( new ScopeDependencySelector( "transitive-2-scope" ) ); + result = collector.collectDependencies( session, request ); + assertEqualSubtree( transitive2ExclusionTree, result.getRoot() ); + + // Same test as above but with root artifact instead of root dependency. + this.session.setDependencySelector( null ); + final CollectRequest rootArtifactRequest = new CollectRequest(); + rootArtifactRequest.setRootArtifact( new DefaultArtifact( "gid:root:ext:ver" ) ); + rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "direct-scope" ) ); + rootArtifactRequest.setRepositories( Arrays.asList( repository ) ); + + result = collector.collectDependencies( session, rootArtifactRequest ); + assertNull( result.getRoot().getDependency() ); + assertEqualSubtree( allNodes, this.toDependencyResult( result.getRoot(), "root-scope", null ) ); + + /* + A dependency selector that filters transitive dependencies based on their scope. Direct dependencies are always + included regardless of their scope. + */ + // Include all. + this.session.setDependencySelector( new ScopeDependencySelector() ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertNull( result.getRoot().getDependency() ); + assertEqualSubtree( allNodes, this.toDependencyResult( result.getRoot(), "root-scope", null ) ); + + // Exclude direct scope equals include all as direct dependencies are always included. + this.session.setDependencySelector( new ScopeDependencySelector( "direct-scope" ) ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertNull( result.getRoot().getDependency() ); + assertEqualSubtree( allNodes, this.toDependencyResult( result.getRoot(), "root-scope", null ) ); + + // Exclude scope of transitive of direct. + this.session.setDependencySelector( new ScopeDependencySelector( "transitive-1-scope" ) ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertNull( result.getRoot().getDependency() ); + assertEqualSubtree( transitive1ExclusionTree, this.toDependencyResult( result.getRoot(), "root-scope", null ) ); + + // Exclude scope of transitive of transitive of direct dependency. + this.session.setDependencySelector( new ScopeDependencySelector( "transitive-2-scope" ) ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertNull( result.getRoot().getDependency() ); + assertEqualSubtree( transitive2ExclusionTree, this.toDependencyResult( result.getRoot(), "root-scope", null ) ); + } + + @Test + public void testSelectionWithOptionalDependencySelector() + throws DependencyCollectionException, IOException + { + collector.setArtifactDescriptorReader( newReader( "selection/optional/" ) ); + parser = new DependencyGraphParser( "artifact-descriptions/selection/optional/" ); + session.setDependencySelector( null ); + + final DependencyNode allNodes = parser.parseResource( "all-nodes.txt" ); + final DependencyNode optionalTransitiveExclusionTree = + parser.parseResource( "optional-transitive-exclusion-tree.txt" ); + + final Dependency root = newDep( "gid:root:ext:ver", "root-scope" ).setOptional( true ); + // No selector. Include all. + final CollectRequest request = new CollectRequest( root, Arrays.asList( repository ) ); + CollectResult result = collector.collectDependencies( session, request ); + assertEqualSubtree( allNodes, result.getRoot() ); + + // A dependency selector that excludes transitive optional dependencies. + this.session.setDependencySelector( new OptionalDependencySelector() ); + result = collector.collectDependencies( session, request ); + assertEqualSubtree( optionalTransitiveExclusionTree, result.getRoot() ); + + // Same test as above but with root artifact instead of root dependency. + this.session.setDependencySelector( null ); + final Artifact rootArtifact = new DefaultArtifact( "gid:root:ext:ver" ); + final CollectRequest rootArtifactRequest = new CollectRequest(); + rootArtifactRequest.setRootArtifact( rootArtifact ); + rootArtifactRequest.addDependency( newDep( "gid:direct:ext:ver", "direct-scope" ).setOptional( true ) ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertNull( result.getRoot().getDependency() ); + assertEqualSubtree( allNodes, this.toDependencyResult( result.getRoot(), "root-scope", true ) ); + + // A dependency selector that excludes transitive optional dependencies. + this.session.setDependencySelector( new OptionalDependencySelector() ); + result = collector.collectDependencies( session, rootArtifactRequest ); + assertNull( result.getRoot().getDependency() ); + assertEqualSubtree( optionalTransitiveExclusionTree, this.toDependencyResult( result.getRoot(), "root-scope", + true ) ); + + } + + private DependencyNode toDependencyResult( final DependencyNode root, final String rootScope, + final Boolean optional ) + { + // Make the root artifact resultion result a dependency resolution result for the subtree check. + assertNull( "Expected root artifact resolution result.", root.getDependency() ); + final DefaultDependencyNode defaultNode = + new DefaultDependencyNode( new Dependency( root.getArtifact(), rootScope ) ); + + defaultNode.setChildren( root.getChildren() ); + + if ( optional != null ) + { + defaultNode.setOptional( optional ); + } + + return defaultNode; + } + static class TestDependencyManager implements DependencyManager { diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/default-management-tree.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/default-management-tree.txt new file mode 100644 index 000000000..d0a194664 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/default-management-tree.txt @@ -0,0 +1,6 @@ +gid:root:ext:ver compile ++- gid:direct:ext:managed-by-dominant-request compile + +- gid:transitive-1:ext:managed-by-root compile + +- gid:transitive-2:ext:managed-by-direct compile + +- gid:transitive-3:ext:managed-by-transitive-1 compile + +- gid:transitive-4:ext:managed-by-transitive-2 compile diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_direct_managed-by-dominant-request.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_direct_managed-by-dominant-request.ini new file mode 100644 index 000000000..94ba9fb4d --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_direct_managed-by-dominant-request.ini @@ -0,0 +1,5 @@ +[dependencies] +gid:transitive-1:ext:ver +[manageddependencies] +gid:transitive-1:ext:must-retain-core-management +gid:transitive-2:ext:managed-by-direct \ No newline at end of file diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_direct_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_direct_ver.ini new file mode 100644 index 000000000..94ba9fb4d --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_direct_ver.ini @@ -0,0 +1,5 @@ +[dependencies] +gid:transitive-1:ext:ver +[manageddependencies] +gid:transitive-1:ext:must-retain-core-management +gid:transitive-2:ext:managed-by-direct \ No newline at end of file diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_root_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_root_ver.ini new file mode 100644 index 000000000..5ac544ad1 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_root_ver.ini @@ -0,0 +1,5 @@ +[dependencies] +gid:direct:ext:ver +[manageddependencies] +gid:direct:ext:must-be-ignored-for-maven-2-and-3-compat +gid:transitive-1:ext:managed-by-root \ No newline at end of file diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-1_managed-by-root.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-1_managed-by-root.ini new file mode 100644 index 000000000..8fd9f0de2 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-1_managed-by-root.ini @@ -0,0 +1,5 @@ +[dependencies] +gid:transitive-2:ext:ver +[manageddependencies] +gid:transitive-2:ext:must-retain-core-management +gid:transitive-3:ext:managed-by-transitive-1 \ No newline at end of file diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-2_managed-by-direct.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-2_managed-by-direct.ini new file mode 100644 index 000000000..96cc8f580 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-2_managed-by-direct.ini @@ -0,0 +1,5 @@ +[dependencies] +gid:transitive-3:ext:ver +[manageddependencies] +gid:transitive-3:ext:must-retain-core-management +gid:transitive-4:ext:managed-by-transitive-2 \ No newline at end of file diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-3_managed-by-transitive-1.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-3_managed-by-transitive-1.ini new file mode 100644 index 000000000..2b8f3cf46 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-3_managed-by-transitive-1.ini @@ -0,0 +1,4 @@ +[dependencies] +gid:transitive-4:ext:ver +[manageddependencies] +gid:transitive-4:ext:must-retain-core-management diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-4_managed-by-transitive-2.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-4_managed-by-transitive-2.ini new file mode 100644 index 000000000..61a252c23 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/gid_transitive-4_managed-by-transitive-2.ini @@ -0,0 +1 @@ +[dependencies] diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/management-tree.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/management-tree.txt new file mode 100644 index 000000000..1371426ca --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/managed/management-tree.txt @@ -0,0 +1,6 @@ +gid:root:ext:ver compile ++- gid:direct:ext:ver compile + +- gid:transitive-1:ext:managed-by-root compile + +- gid:transitive-2:ext:managed-by-direct compile + +- gid:transitive-3:ext:managed-by-transitive-1 compile + +- gid:transitive-4:ext:managed-by-transitive-2 compile diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/all-nodes.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/all-nodes.txt new file mode 100644 index 000000000..6caeee1d9 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/all-nodes.txt @@ -0,0 +1,4 @@ +gid:root:ext:ver root-scope ++- gid:direct-of-root:ext:ver direct-of-root-scope + +- gid:transitive-of-root:ext:ver transitive-of-root-scope + +- gid:transitive-of-transitive-of-root:ext:ver transitive-of-transitive-of-root-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/direct-of-root.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/direct-of-root.txt new file mode 100644 index 000000000..e7b354d74 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/direct-of-root.txt @@ -0,0 +1 @@ +gid:root:ext:ver root-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_direct-of-root_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_direct-of-root_ver.ini new file mode 100644 index 000000000..a801f3f45 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_direct-of-root_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:transitive-of-root:ext:ver:transitive-of-root-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_root_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_root_ver.ini new file mode 100644 index 000000000..37fe9ac0b --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_root_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:direct-of-root:ext:ver:direct-of-root-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-root_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-root_ver.ini new file mode 100644 index 000000000..e34fa0497 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-root_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:transitive-of-transitive-of-root:ext:ver:transitive-of-transitive-of-root-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-transitive-of-root_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-transitive-of-root_ver.ini new file mode 100644 index 000000000..61a252c23 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/gid_transitive-of-transitive-of-root_ver.ini @@ -0,0 +1 @@ +[dependencies] diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-root.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-root.txt new file mode 100644 index 000000000..dbee99b23 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-root.txt @@ -0,0 +1,2 @@ +gid:root:ext:ver root-scope ++- gid:direct-of-root:ext:ver direct-of-root-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-transitive-of-root.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-transitive-of-root.txt new file mode 100644 index 000000000..ef3dc7488 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/managed/transitive-of-transitive-of-root.txt @@ -0,0 +1,3 @@ +gid:root:ext:ver root-scope ++- gid:direct-of-root:ext:ver direct-of-root-scope + +- gid:transitive-of-root:ext:ver transitive-of-root-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/all-nodes.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/all-nodes.txt new file mode 100644 index 000000000..89de14fab --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/all-nodes.txt @@ -0,0 +1,4 @@ +gid:root:ext:ver root-scope optional ++- gid:direct:ext:ver direct-scope optional + +- gid:transitive-1:ext:ver transitive-1-scope optional + +- gid:transitive-2:ext:ver transitive-2-scope optional diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_direct_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_direct_ver.ini new file mode 100644 index 000000000..0bcf1f8f4 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_direct_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:transitive-1:ext:ver:transitive-1-scope:optional diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_root_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_root_ver.ini new file mode 100644 index 000000000..a7e6ac130 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_root_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:direct:ext:ver:direct-scope:optional diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-1_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-1_ver.ini new file mode 100644 index 000000000..7428741b9 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-1_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:transitive-2:ext:ver:transitive-2-scope:optional diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-2_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-2_ver.ini new file mode 100644 index 000000000..61a252c23 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/gid_transitive-2_ver.ini @@ -0,0 +1 @@ +[dependencies] diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/optional-transitive-exclusion-tree.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/optional-transitive-exclusion-tree.txt new file mode 100644 index 000000000..34fa909f0 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/optional/optional-transitive-exclusion-tree.txt @@ -0,0 +1,2 @@ +gid:root:ext:ver root-scope optional ++- gid:direct:ext:ver direct-scope optional diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/all-nodes.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/all-nodes.txt new file mode 100644 index 000000000..8bec12ebf --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/all-nodes.txt @@ -0,0 +1,4 @@ +gid:root:ext:ver root-scope ++- gid:direct:ext:ver direct-scope + +- gid:transitive-1:ext:ver transitive-1-scope + +- gid:transitive-2:ext:ver transitive-2-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_direct_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_direct_ver.ini new file mode 100644 index 000000000..aad5f7a20 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_direct_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:transitive-1:ext:ver:transitive-1-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_root_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_root_ver.ini new file mode 100644 index 000000000..175e571b9 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_root_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:direct:ext:ver:direct-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-1_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-1_ver.ini new file mode 100644 index 000000000..56b4533dd --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-1_ver.ini @@ -0,0 +1,2 @@ +[dependencies] +gid:transitive-2:ext:ver:transitive-2-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-2_ver.ini b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-2_ver.ini new file mode 100644 index 000000000..61a252c23 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/gid_transitive-2_ver.ini @@ -0,0 +1 @@ +[dependencies] diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-1-exclusion-tree.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-1-exclusion-tree.txt new file mode 100644 index 000000000..509afac4a --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-1-exclusion-tree.txt @@ -0,0 +1,2 @@ +gid:root:ext:ver root-scope ++- gid:direct:ext:ver direct-scope diff --git a/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-2-exclusion-tree.txt b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-2-exclusion-tree.txt new file mode 100644 index 000000000..b3b056369 --- /dev/null +++ b/maven-resolver-impl/src/test/resources/artifact-descriptions/selection/scope/transitive-2-exclusion-tree.txt @@ -0,0 +1,3 @@ +gid:root:ext:ver root-scope ++- gid:direct:ext:ver direct-scope + +- gid:transitive-1:ext:ver transitive-1-scope diff --git a/maven-resolver-spi/pom.xml b/maven-resolver-spi/pom.xml index f8352dcb0..c0e51d4ae 100644 --- a/maven-resolver-spi/pom.xml +++ b/maven-resolver-spi/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-spi diff --git a/maven-resolver-test-util/pom.xml b/maven-resolver-test-util/pom.xml index 9d0a34909..54e39c27a 100644 --- a/maven-resolver-test-util/pom.xml +++ b/maven-resolver-test-util/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-test-util diff --git a/maven-resolver-transport-classpath/pom.xml b/maven-resolver-transport-classpath/pom.xml index 91052925b..72588df21 100644 --- a/maven-resolver-transport-classpath/pom.xml +++ b/maven-resolver-transport-classpath/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-transport-classpath diff --git a/maven-resolver-transport-file/pom.xml b/maven-resolver-transport-file/pom.xml index ee670189c..2c1d344b5 100644 --- a/maven-resolver-transport-file/pom.xml +++ b/maven-resolver-transport-file/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-transport-file diff --git a/maven-resolver-transport-http/pom.xml b/maven-resolver-transport-http/pom.xml index dce3dcd98..d7876110e 100644 --- a/maven-resolver-transport-http/pom.xml +++ b/maven-resolver-transport-http/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-transport-http diff --git a/maven-resolver-transport-wagon/pom.xml b/maven-resolver-transport-wagon/pom.xml index 5371d2a7d..9380e84aa 100644 --- a/maven-resolver-transport-wagon/pom.xml +++ b/maven-resolver-transport-wagon/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-transport-wagon diff --git a/maven-resolver-util/pom.xml b/maven-resolver-util/pom.xml index bcd5b4b21..00153ef52 100644 --- a/maven-resolver-util/pom.xml +++ b/maven-resolver-util/pom.xml @@ -25,7 +25,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT maven-resolver-util diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java index 88c5d62d0..4273a9de5 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManager.java @@ -45,14 +45,39 @@ public final class ClassicDependencyManager private final Map managedVersions; + /** + * @since 1.2.0 + */ + private final Map managedVersionsSourceHints; + private final Map managedScopes; + /** + * @since 1.2.0 + */ + private final Map managedScopesSourceHints; + private final Map managedOptionals; + /** + * @since 1.2.0 + */ + private final Map managedOptionalsSourceHints; + private final Map managedLocalPaths; + /** + * @since 1.2.0 + */ + private final Map managedLocalPathsSourceHints; + private final Map> managedExclusions; + /** + * @since 1.2.0 + */ + private final Map> managedExclusionsSourceHints; + private int hashCode; /** @@ -61,21 +86,37 @@ public final class ClassicDependencyManager public ClassicDependencyManager() { this( 0, Collections.emptyMap(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), Collections.emptyMap(), - Collections.>emptyMap() ); + Collections.emptyMap(), Collections.emptyMap(), + Collections.>emptyMap(), + Collections.>emptyMap() ); } - private ClassicDependencyManager( int depth, Map managedVersions, - Map managedScopes, Map managedOptionals, + private ClassicDependencyManager( int depth, + Map managedVersions, + Map managedVersionsSourceHints, + Map managedScopes, + Map managedScopesSourceHints, + Map managedOptionals, + Map managedOptionalsSourceHints, Map managedLocalPaths, - Map> managedExclusions ) + Map managedLocalPathsSourceHints, + Map> managedExclusions, + Map> managedExclusionsSourceHints ) { + super(); this.depth = depth; this.managedVersions = managedVersions; + this.managedVersionsSourceHints = managedVersionsSourceHints; this.managedScopes = managedScopes; + this.managedScopesSourceHints = managedScopesSourceHints; this.managedOptionals = managedOptionals; + this.managedOptionalsSourceHints = managedOptionalsSourceHints; this.managedLocalPaths = managedLocalPaths; + this.managedLocalPathsSourceHints = managedLocalPathsSourceHints; this.managedExclusions = managedExclusions; + this.managedExclusionsSourceHints = managedExclusionsSourceHints; } public DependencyManager deriveChildManager( DependencyCollectionContext context ) @@ -86,15 +127,23 @@ public DependencyManager deriveChildManager( DependencyCollectionContext context } else if ( depth == 1 ) { - return new ClassicDependencyManager( depth + 1, managedVersions, managedScopes, managedOptionals, - managedLocalPaths, managedExclusions ); + return new ClassicDependencyManager( depth + 1, managedVersions, managedVersionsSourceHints, + managedScopes, managedScopesSourceHints, + managedOptionals, managedOptionalsSourceHints, + managedLocalPaths, managedLocalPathsSourceHints, + managedExclusions, managedExclusionsSourceHints ); } - Map managedVersions = this.managedVersions; - Map managedScopes = this.managedScopes; - Map managedOptionals = this.managedOptionals; - Map managedLocalPaths = this.managedLocalPaths; - Map> managedExclusions = this.managedExclusions; + Map versions = this.managedVersions; + Map versionsSourceHints = this.managedVersionsSourceHints; + Map scopes = this.managedScopes; + Map scopesSourceHints = this.managedScopesSourceHints; + Map optionals = this.managedOptionals; + Map optionalsSourceHints = this.managedOptionalsSourceHints; + Map localPaths = this.managedLocalPaths; + Map localPathsSourceHints = this.managedLocalPathsSourceHints; + Map> exclusions = this.managedExclusions; + Map> exclusionsSourceHints = this.managedExclusionsSourceHints; for ( Dependency managedDependency : context.getManagedDependencies() ) { @@ -102,64 +151,86 @@ else if ( depth == 1 ) Object key = getKey( artifact ); String version = artifact.getVersion(); - if ( version.length() > 0 && !managedVersions.containsKey( key ) ) + if ( version.length() > 0 && !versions.containsKey( key ) ) { - if ( managedVersions == this.managedVersions ) + if ( versions == this.managedVersions ) { - managedVersions = new HashMap( this.managedVersions ); + versions = new HashMap( this.managedVersions ); + versionsSourceHints = new HashMap( this.managedVersionsSourceHints ); } - managedVersions.put( key, version ); + versions.put( key, version ); + versionsSourceHints.put( key, managedDependency.getSourceHint() ); } String scope = managedDependency.getScope(); - if ( scope.length() > 0 && !managedScopes.containsKey( key ) ) + if ( scope.length() > 0 && !scopes.containsKey( key ) ) { - if ( managedScopes == this.managedScopes ) + if ( scopes == this.managedScopes ) { - managedScopes = new HashMap( this.managedScopes ); + scopes = new HashMap( this.managedScopes ); + scopesSourceHints = new HashMap( this.managedScopesSourceHints ); } - managedScopes.put( key, scope ); + scopes.put( key, scope ); + scopesSourceHints.put( key, managedDependency.getSourceHint() ); } Boolean optional = managedDependency.getOptional(); - if ( optional != null && !managedOptionals.containsKey( key ) ) + if ( optional != null && !optionals.containsKey( key ) ) { - if ( managedOptionals == this.managedOptionals ) + if ( optionals == this.managedOptionals ) { - managedOptionals = new HashMap( this.managedOptionals ); + optionals = new HashMap( this.managedOptionals ); + optionalsSourceHints = new HashMap( this.managedOptionalsSourceHints ); } - managedOptionals.put( key, optional ); + optionals.put( key, optional ); + optionalsSourceHints.put( key, managedDependency.getSourceHint() ); } String localPath = managedDependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ); - if ( localPath != null && !managedLocalPaths.containsKey( key ) ) + if ( localPath != null && !localPaths.containsKey( key ) ) { - if ( managedLocalPaths == this.managedLocalPaths ) + if ( localPaths == this.managedLocalPaths ) { - managedLocalPaths = new HashMap( this.managedLocalPaths ); + localPaths = new HashMap( this.managedLocalPaths ); + localPathsSourceHints = new HashMap( this.managedLocalPathsSourceHints ); } - managedLocalPaths.put( key, localPath ); + localPaths.put( key, localPath ); + localPathsSourceHints.put( key, managedDependency.getSourceHint() ); } - Collection exclusions = managedDependency.getExclusions(); - if ( !exclusions.isEmpty() ) + if ( !managedDependency.getExclusions().isEmpty() ) { - if ( managedExclusions == this.managedExclusions ) + if ( exclusions == this.managedExclusions ) { - managedExclusions = new HashMap>( this.managedExclusions ); + exclusions = new HashMap>( this.managedExclusions ); + exclusionsSourceHints = new HashMap>( this.managedExclusionsSourceHints ); } - Collection managed = managedExclusions.get( key ); + Collection managed = exclusions.get( key ); if ( managed == null ) { managed = new LinkedHashSet(); - managedExclusions.put( key, managed ); + exclusions.put( key, managed ); + } + managed.addAll( managedDependency.getExclusions() ); + + Collection managedSourceHints = exclusionsSourceHints.get( key ); + if ( managedSourceHints == null ) + { + managedSourceHints = new LinkedHashSet(); + exclusionsSourceHints.put( key, managedSourceHints ); } - managed.addAll( exclusions ); + + managedSourceHints.add( managedDependency.getSourceHint() ); } } - return new ClassicDependencyManager( depth + 1, managedVersions, managedScopes, managedOptionals, - managedLocalPaths, managedExclusions ); + return new ClassicDependencyManager( depth + 1, + versions, versionsSourceHints, + scopes, scopesSourceHints, + optionals, optionalsSourceHints, + localPaths, localPathsSourceHints, + exclusions, exclusionsSourceHints ); + } public DependencyManagement manageDependency( Dependency dependency ) @@ -178,6 +249,7 @@ public DependencyManagement manageDependency( Dependency dependency ) management = new DependencyManagement(); } management.setVersion( version ); + management.setVersionSourceHint( this.managedVersionsSourceHints.get( key ) ); } String scope = managedScopes.get( key ); @@ -188,19 +260,21 @@ public DependencyManagement manageDependency( Dependency dependency ) management = new DependencyManagement(); } management.setScope( scope ); + management.setScopeSourceHint( this.managedScopesSourceHints.get( key ) ); if ( !JavaScopes.SYSTEM.equals( scope ) - && dependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null ) + && dependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null ) { Map properties = new HashMap( dependency.getArtifact().getProperties() ); properties.remove( ArtifactProperties.LOCAL_PATH ); management.setProperties( properties ); + management.setPropertiesSourceHint( this.managedScopesSourceHints.get( key ) ); } } if ( ( scope != null && JavaScopes.SYSTEM.equals( scope ) ) - || ( scope == null && JavaScopes.SYSTEM.equals( dependency.getScope() ) ) ) + || ( scope == null && JavaScopes.SYSTEM.equals( dependency.getScope() ) ) ) { String localPath = managedLocalPaths.get( key ); if ( localPath != null ) @@ -213,6 +287,7 @@ public DependencyManagement manageDependency( Dependency dependency ) new HashMap( dependency.getArtifact().getProperties() ); properties.put( ArtifactProperties.LOCAL_PATH, localPath ); management.setProperties( properties ); + management.setPropertiesSourceHint( this.managedLocalPathsSourceHints.get( key ) ); } } @@ -224,6 +299,7 @@ public DependencyManagement manageDependency( Dependency dependency ) management = new DependencyManagement(); } management.setOptional( optional ); + management.setOptionalitySourceHint( this.managedOptionalsSourceHints.get( key ) ); } } @@ -237,6 +313,12 @@ public DependencyManagement manageDependency( Dependency dependency ) Collection result = new LinkedHashSet( dependency.getExclusions() ); result.addAll( exclusions ); management.setExclusions( result ); + + final Object sourceHint = this.managedExclusionsSourceHints.get( key ); + if ( sourceHint != null ) + { + management.setExclusionsSourceHint( sourceHint.toString() ); + } } return management; @@ -261,8 +343,8 @@ else if ( null == obj || !getClass().equals( obj.getClass() ) ) ClassicDependencyManager that = (ClassicDependencyManager) obj; return depth == that.depth && managedVersions.equals( that.managedVersions ) - && managedScopes.equals( that.managedScopes ) && managedOptionals.equals( that.managedOptionals ) - && managedExclusions.equals( that.managedExclusions ); + && managedScopes.equals( that.managedScopes ) && managedOptionals.equals( that.managedOptionals ) + && managedExclusions.equals( that.managedExclusions ); } @Override @@ -311,9 +393,9 @@ else if ( !( obj instanceof Key ) ) } Key that = (Key) obj; return artifact.getArtifactId().equals( that.artifact.getArtifactId() ) - && artifact.getGroupId().equals( that.artifact.getGroupId() ) - && artifact.getExtension().equals( that.artifact.getExtension() ) - && artifact.getClassifier().equals( that.artifact.getClassifier() ); + && artifact.getGroupId().equals( that.artifact.getGroupId() ) + && artifact.getExtension().equals( that.artifact.getExtension() ) + && artifact.getClassifier().equals( that.artifact.getClassifier() ); } @Override diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DefaultDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DefaultDependencyManager.java new file mode 100644 index 000000000..d19caa56b --- /dev/null +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DefaultDependencyManager.java @@ -0,0 +1,383 @@ +package org.eclipse.aether.util.graph.manager; + +/* + * 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.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; + +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.ArtifactProperties; +import org.eclipse.aether.collection.DependencyCollectionContext; +import org.eclipse.aether.collection.DependencyManagement; +import org.eclipse.aether.collection.DependencyManager; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.Exclusion; +import org.eclipse.aether.util.artifact.JavaScopes; + +/** + * A dependency manager managing dependencies on all levels supporting transitive dependency management. + *

+ * Note:Unlike the {@code ClassicDependencyManager} and the {@code TransitiveDependencyManager} this + * implementation applies management also on the first level. This is considered the resolver default behaviour. It + * ignores all management overrides supported by the {@code MavenModelBuilder}. + *

+ * + * @author Christian Schulte + * @since 1.2.0 + */ +public final class DefaultDependencyManager + implements DependencyManager +{ + + private final Map managedVersions; + + private final Map managedVersionsSourceHints; + + private final Map managedScopes; + + private final Map managedScopesSourceHints; + + private final Map managedOptionals; + + private final Map managedOptionalsSourceHints; + + private final Map managedLocalPaths; + + private final Map managedLocalPathsSourceHints; + + private final Map> managedExclusions; + + private final Map> managedExclusionsSourceHints; + + private int hashCode; + + /** + * Creates a new dependency manager without any management information. + */ + public DefaultDependencyManager() + { + this( Collections.emptyMap(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyMap(), + Collections.>emptyMap(), + Collections.>emptyMap() ); + } + + private DefaultDependencyManager( final Map managedVersions, + final Map managedVersionsSourceHints, + final Map managedScopes, + final Map managedScopesSourceHints, + final Map managedOptionals, + final Map managedOptionalsSourceHints, + final Map managedLocalPaths, + final Map managedLocalPathsSourceHints, + final Map> managedExclusions, + final Map> managedExclusionsSourceHints ) + { + super(); + this.managedVersions = managedVersions; + this.managedVersionsSourceHints = managedVersionsSourceHints; + this.managedScopes = managedScopes; + this.managedScopesSourceHints = managedScopesSourceHints; + this.managedOptionals = managedOptionals; + this.managedOptionalsSourceHints = managedOptionalsSourceHints; + this.managedLocalPaths = managedLocalPaths; + this.managedLocalPathsSourceHints = managedLocalPathsSourceHints; + this.managedExclusions = managedExclusions; + this.managedExclusionsSourceHints = managedExclusionsSourceHints; + } + + public DependencyManager deriveChildManager( final DependencyCollectionContext context ) + { + Map versions = this.managedVersions; + Map versionsSourceHints = this.managedVersionsSourceHints; + Map scopes = this.managedScopes; + Map scopesSourceHints = this.managedScopesSourceHints; + Map optionals = this.managedOptionals; + Map optionalsSourceHints = this.managedOptionalsSourceHints; + Map localPaths = this.managedLocalPaths; + Map localPathsSourceHints = this.managedLocalPathsSourceHints; + Map> exclusions = this.managedExclusions; + Map> exclusionsSourceHints = this.managedExclusionsSourceHints; + + for ( Dependency managedDependency : context.getManagedDependencies() ) + { + Artifact artifact = managedDependency.getArtifact(); + Object key = getKey( artifact ); + + String version = artifact.getVersion(); + if ( version.length() > 0 && !versions.containsKey( key ) ) + { + if ( versions == this.managedVersions ) + { + versions = new HashMap( this.managedVersions ); + versionsSourceHints = new HashMap( this.managedVersionsSourceHints ); + } + versions.put( key, version ); + versionsSourceHints.put( key, managedDependency.getSourceHint() ); + } + + String scope = managedDependency.getScope(); + if ( scope.length() > 0 && !scopes.containsKey( key ) ) + { + if ( scopes == this.managedScopes ) + { + scopes = new HashMap( this.managedScopes ); + scopesSourceHints = new HashMap( this.managedScopesSourceHints ); + } + scopes.put( key, scope ); + scopesSourceHints.put( key, managedDependency.getSourceHint() ); + } + + Boolean optional = managedDependency.getOptional(); + if ( optional != null && !optionals.containsKey( key ) ) + { + if ( optionals == this.managedOptionals ) + { + optionals = new HashMap( this.managedOptionals ); + optionalsSourceHints = new HashMap( this.managedOptionalsSourceHints ); + } + optionals.put( key, optional ); + optionalsSourceHints.put( key, managedDependency.getSourceHint() ); + } + + String localPath = managedDependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ); + if ( localPath != null && !localPaths.containsKey( key ) ) + { + if ( localPaths == this.managedLocalPaths ) + { + localPaths = new HashMap( this.managedLocalPaths ); + localPathsSourceHints = new HashMap( this.managedLocalPathsSourceHints ); + } + localPaths.put( key, localPath ); + localPathsSourceHints.put( key, managedDependency.getSourceHint() ); + } + + if ( !managedDependency.getExclusions().isEmpty() ) + { + if ( exclusions == this.managedExclusions ) + { + exclusions = new HashMap>( this.managedExclusions ); + exclusionsSourceHints = + new HashMap>( this.managedExclusionsSourceHints ); + + } + Collection managed = exclusions.get( key ); + if ( managed == null ) + { + managed = new LinkedHashSet(); + exclusions.put( key, managed ); + } + managed.addAll( managedDependency.getExclusions() ); + + Collection managedSources = exclusionsSourceHints.get( key ); + if ( managedSources == null ) + { + managedSources = new LinkedHashSet(); + exclusionsSourceHints.put( key, managedSources ); + } + + managedSources.add( managedDependency.getSourceHint() ); + } + } + + return new DefaultDependencyManager( versions, versionsSourceHints, scopes, scopesSourceHints, optionals, + optionalsSourceHints, localPaths, localPathsSourceHints, exclusions, + exclusionsSourceHints ); + + } + + public DependencyManagement manageDependency( Dependency dependency ) + { + DependencyManagement management = null; + + Object key = getKey( dependency.getArtifact() ); + + String version = managedVersions.get( key ); + if ( version != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + management.setVersion( version ); + management.setVersionSourceHint( this.managedVersionsSourceHints.get( key ) ); + } + + String scope = managedScopes.get( key ); + if ( scope != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + management.setScope( scope ); + management.setScopeSourceHint( this.managedScopesSourceHints.get( key ) ); + + if ( !JavaScopes.SYSTEM.equals( scope ) + && dependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null ) + { + Map properties = + new HashMap( dependency.getArtifact().getProperties() ); + + properties.remove( ArtifactProperties.LOCAL_PATH ); + management.setProperties( properties ); + management.setPropertiesSourceHint( this.managedScopesSourceHints.get( key ) ); + } + } + + if ( ( scope != null && JavaScopes.SYSTEM.equals( scope ) ) + || ( scope == null && JavaScopes.SYSTEM.equals( dependency.getScope() ) ) ) + { + String localPath = managedLocalPaths.get( key ); + if ( localPath != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + + Map properties = + new HashMap( dependency.getArtifact().getProperties() ); + + properties.put( ArtifactProperties.LOCAL_PATH, localPath ); + management.setProperties( properties ); + management.setPropertiesSourceHint( this.managedLocalPathsSourceHints.get( key ) ); + } + } + + Boolean optional = managedOptionals.get( key ); + if ( optional != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + management.setOptional( optional ); + management.setOptionalitySourceHint( this.managedOptionalsSourceHints.get( key ) ); + } + + Collection exclusions = managedExclusions.get( key ); + if ( exclusions != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + Collection result = new LinkedHashSet( dependency.getExclusions() ); + result.addAll( exclusions ); + management.setExclusions( result ); + + final Object sourceHint = this.managedExclusionsSourceHints.get( key ); + if ( sourceHint != null ) + { + management.setExclusionsSourceHint( sourceHint.toString() ); + } + } + + return management; + } + + private Object getKey( Artifact a ) + { + return new Key( a ); + } + + @Override + public boolean equals( final Object obj ) + { + boolean equal = obj instanceof DefaultDependencyManager; + + if ( equal ) + { + final DefaultDependencyManager that = (DefaultDependencyManager) obj; + equal = this.managedVersions.equals( that.managedVersions ) + && this.managedScopes.equals( that.managedScopes ) + && this.managedOptionals.equals( that.managedOptionals ) + && this.managedExclusions.equals( that.managedExclusions ); + + } + + return equal; + } + + @Override + public int hashCode() + { + if ( this.hashCode == 0 ) + { + int hash = 17; + hash = hash * 31 + this.managedVersions.hashCode(); + hash = hash * 31 + this.managedScopes.hashCode(); + hash = hash * 31 + this.managedOptionals.hashCode(); + hash = hash * 31 + this.managedExclusions.hashCode(); + this.hashCode = hash; + } + return this.hashCode; + } + + static class Key + { + + private final Artifact artifact; + + private final int hashCode; + + Key( final Artifact artifact ) + { + this.artifact = artifact; + + int hash = 17; + hash = hash * 31 + artifact.getGroupId().hashCode(); + hash = hash * 31 + artifact.getArtifactId().hashCode(); + this.hashCode = hash; + } + + @Override + public boolean equals( final Object obj ) + { + boolean equal = obj instanceof Key; + + if ( equal ) + { + final Key that = (Key) obj; + return this.artifact.getArtifactId().equals( that.artifact.getArtifactId() ) + && this.artifact.getGroupId().equals( that.artifact.getGroupId() ) + && this.artifact.getExtension().equals( that.artifact.getExtension() ) + && this.artifact.getClassifier().equals( that.artifact.getClassifier() ); + + } + + return equal; + } + + @Override + public int hashCode() + { + return this.hashCode; + } + + } + +} diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DependencyManagerUtils.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DependencyManagerUtils.java index f549367d7..dd5db312a 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DependencyManagerUtils.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/DependencyManagerUtils.java @@ -46,18 +46,39 @@ public final class DependencyManagerUtils */ public static final String NODE_DATA_PREMANAGED_VERSION = "premanaged.version"; + /** + * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the informational hint + * describing the source declaring the version management is stored. + * @since 1.2.0 + */ + public static final String NODE_DATA_VERSION_MANAGEMENT_SOURCE_HINT = "version.management.source.hint"; + /** * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the original scope is * stored. */ public static final String NODE_DATA_PREMANAGED_SCOPE = "premanaged.scope"; + /** + * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the informational hint + * describing the source declaring the scope management is stored. + * @since 1.2.0 + */ + public static final String NODE_DATA_SCOPE_MANAGEMENT_SOURCE_HINT = "scope.management.source.hint"; + /** * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the original optional * flag is stored. */ public static final String NODE_DATA_PREMANAGED_OPTIONAL = "premanaged.optional"; + /** + * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the informational hint + * describing the source declaring the optionality management is stored. + * @since 1.2.0 + */ + public static final String NODE_DATA_OPTIONALITY_MANAGEMENT_SOURCE_HINT = "optionality.management.source.hint"; + /** * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the original exclusions * are stored. @@ -66,6 +87,13 @@ public final class DependencyManagerUtils */ public static final String NODE_DATA_PREMANAGED_EXCLUSIONS = "premanaged.exclusions"; + /** + * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the informational hint + * describing the source declaring the exclusion management is stored. + * @since 1.2.0 + */ + public static final String NODE_DATA_EXCLUSIONS_MANAGEMENT_SOURCE_HINT = "exlusions.management.source.hint"; + /** * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the original properties * are stored. @@ -74,6 +102,13 @@ public final class DependencyManagerUtils */ public static final String NODE_DATA_PREMANAGED_PROPERTIES = "premanaged.properties"; + /** + * The key in the dependency node's {@link DependencyNode#getData() custom data} under which the informational hint + * describing the source declaring the properties management is stored. + * @since 1.2.0 + */ + public static final String NODE_DATA_PROPERTIES_MANAGEMENT_SOURCE_HINT = "properties.management.source.hint"; + /** * Gets the version or version range of the specified dependency node before dependency management was applied (if * any). @@ -81,7 +116,7 @@ public final class DependencyManagerUtils * @param node The dependency node to retrieve the premanaged data for, must not be {@code null}. * * @return The node's dependency version before dependency management or {@code null} if the version was not managed - * or if {@link #CONFIG_PROP_VERBOSE} was not enabled. + * or if {@link #CONFIG_PROP_VERBOSE} was not enabled. */ public static String getPremanagedVersion( DependencyNode node ) { @@ -92,13 +127,32 @@ public static String getPremanagedVersion( DependencyNode node ) return cast( node.getData().get( NODE_DATA_PREMANAGED_VERSION ), String.class ); } + /** + * Gets an informational hint describing the source declaring the version management of the specified dependency + * node after dependency management was applied (if any). + * + * @param node The dependency node to retrieve the data of, must not be {@code null}. + * + * @return The node's version management source hint or {@code null} if no such information is available or if + * {@link #CONFIG_PROP_VERBOSE} was not enabled. + * @since 1.2.0 + */ + public static String getVersionManagementSourceHint( DependencyNode node ) + { + if ( ( node.getManagedBits() & DependencyNode.MANAGED_VERSION ) == 0 ) + { + return null; + } + return cast( node.getData().get( NODE_DATA_VERSION_MANAGEMENT_SOURCE_HINT ), String.class ); + } + /** * Gets the scope of the specified dependency node before dependency management was applied (if any). * * @param node The dependency node to retrieve the premanaged data for, must not be {@code null}. * * @return The node's dependency scope before dependency management or {@code null} if the scope was not managed or - * if {@link #CONFIG_PROP_VERBOSE} was not enabled. + * if {@link #CONFIG_PROP_VERBOSE} was not enabled. */ public static String getPremanagedScope( DependencyNode node ) { @@ -109,13 +163,32 @@ public static String getPremanagedScope( DependencyNode node ) return cast( node.getData().get( NODE_DATA_PREMANAGED_SCOPE ), String.class ); } + /** + * Gets an informational hint describing the source declaring the scope management of the specified dependency + * node after dependency management was applied (if any). + * + * @param node The dependency node to retrieve the data of, must not be {@code null}. + * + * @return The node's scope management source hint or {@code null} if no such information is available or if + * {@link #CONFIG_PROP_VERBOSE} was not enabled. + * @since 1.2.0 + */ + public static String getScopeManagementSourceHint( DependencyNode node ) + { + if ( ( node.getManagedBits() & DependencyNode.MANAGED_SCOPE ) == 0 ) + { + return null; + } + return cast( node.getData().get( NODE_DATA_SCOPE_MANAGEMENT_SOURCE_HINT ), String.class ); + } + /** * Gets the optional flag of the specified dependency node before dependency management was applied (if any). * * @param node The dependency node to retrieve the premanaged data for, must not be {@code null}. * * @return The node's optional flag before dependency management or {@code null} if the flag was not managed or if - * {@link #CONFIG_PROP_VERBOSE} was not enabled. + * {@link #CONFIG_PROP_VERBOSE} was not enabled. */ public static Boolean getPremanagedOptional( DependencyNode node ) { @@ -126,13 +199,32 @@ public static Boolean getPremanagedOptional( DependencyNode node ) return cast( node.getData().get( NODE_DATA_PREMANAGED_OPTIONAL ), Boolean.class ); } + /** + * Gets an informational hint describing the source declaring the optionality management of the specified + * dependency node after dependency management was applied (if any). + * + * @param node The dependency node to retrieve the data of, must not be {@code null}. + * + * @return The node's optionality management source hint or {@code null} if no such information is available or if + * {@link #CONFIG_PROP_VERBOSE} was not enabled. + * @since 1.2.0 + */ + public static String getOptionalityManagementSourceHint( DependencyNode node ) + { + if ( ( node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL ) == 0 ) + { + return null; + } + return cast( node.getData().get( NODE_DATA_OPTIONALITY_MANAGEMENT_SOURCE_HINT ), String.class ); + } + /** * Gets the {@code Exclusion}s of the specified dependency node before dependency management was applied (if any). * * @param node The dependency node to retrieve the premanaged data for, must not be {@code null}. * * @return The nodes' {@code Exclusion}s before dependency management or {@code null} if exclusions were not managed - * or if {@link #CONFIG_PROP_VERBOSE} was not enabled. + * or if {@link #CONFIG_PROP_VERBOSE} was not enabled. * * @since 1.1.0 */ @@ -146,13 +238,32 @@ public static Collection getPremanagedExclusions( DependencyNode node return cast( node.getData().get( NODE_DATA_PREMANAGED_EXCLUSIONS ), Collection.class ); } + /** + * Gets an informational hint describing the source declaring the exclusions management of the specified dependency + * node after dependency management was applied (if any). + * + * @param node The dependency node to retrieve the data of, must not be {@code null}. + * + * @return The node's exclusions management source hint or {@code null} if no such information is available or if + * {@link #CONFIG_PROP_VERBOSE} was not enabled. + * @since 1.2.0 + */ + public static String getExclusionsManagementSourceHint( DependencyNode node ) + { + if ( ( node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS ) == 0 ) + { + return null; + } + return cast( node.getData().get( NODE_DATA_EXCLUSIONS_MANAGEMENT_SOURCE_HINT ), String.class ); + } + /** * Gets the properties of the specified dependency node before dependency management was applied (if any). * * @param node The dependency node to retrieve the premanaged data for, must not be {@code null}. * * @return The nodes' properties before dependency management or {@code null} if properties were not managed or if - * {@link #CONFIG_PROP_VERBOSE} was not enabled. + * {@link #CONFIG_PROP_VERBOSE} was not enabled. * * @since 1.1.0 */ @@ -166,6 +277,25 @@ public static Map getPremanagedProperties( DependencyNode node ) return cast( node.getData().get( NODE_DATA_PREMANAGED_PROPERTIES ), Map.class ); } + /** + * Gets an informational hint describing the source declaring the properties management of the specified dependency + * node after dependency management was applied (if any). + * + * @param node The dependency node to retrieve the data of, must not be {@code null}. + * + * @return The node's properties management source hint or {@code null} if no such information is available or if + * {@link #CONFIG_PROP_VERBOSE} was not enabled. + * @since 1.2.0 + */ + public static String getPropertiesManagementSourceHint( DependencyNode node ) + { + if ( ( node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS ) == 0 ) + { + return null; + } + return cast( node.getData().get( NODE_DATA_EXCLUSIONS_MANAGEMENT_SOURCE_HINT ), String.class ); + } + private static T cast( Object obj, Class type ) { return type.isInstance( obj ) ? type.cast( obj ) : null; diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java new file mode 100644 index 000000000..3a5195c29 --- /dev/null +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/TransitiveDependencyManager.java @@ -0,0 +1,387 @@ +package org.eclipse.aether.util.graph.manager; + +/* + * 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.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; + +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.ArtifactProperties; +import org.eclipse.aether.collection.DependencyCollectionContext; +import org.eclipse.aether.collection.DependencyManagement; +import org.eclipse.aether.collection.DependencyManager; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.Exclusion; +import org.eclipse.aether.util.artifact.JavaScopes; + +/** + * A dependency manager managing transitive dependencies supporting transitive dependency management. + * + * @author Christian Schulte + * @since 1.2.0 + */ +public final class TransitiveDependencyManager + implements DependencyManager +{ + + private final Map managedVersions; + + private final Map managedVersionsSourceHints; + + private final Map managedScopes; + + private final Map managedScopesSourceHints; + + private final Map managedOptionals; + + private final Map managedOptionalsSourceHints; + + private final Map managedLocalPaths; + + private final Map managedLocalPathsSourceHints; + + private final Map> managedExclusions; + + private final Map> managedExclusionsSourceHints; + + private final int depth; + + private int hashCode; + + /** + * Creates a new dependency manager without any management information. + */ + public TransitiveDependencyManager() + { + this( 0, Collections.emptyMap(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyMap(), + Collections.emptyMap(), Collections.emptyMap(), + Collections.>emptyMap(), + Collections.>emptyMap() ); + } + + private TransitiveDependencyManager( int depth, + Map managedVersions, + Map managedVersionsSourceHints, + Map managedScopes, + Map managedScopesSourceHints, + Map managedOptionals, + Map managedOptionalsSourceHints, + Map managedLocalPaths, + Map managedLocalPathsSourceHints, + Map> managedExclusions, + Map> managedExclusionsSourceHints ) + { + super(); + this.depth = depth; + this.managedVersions = managedVersions; + this.managedVersionsSourceHints = managedVersionsSourceHints; + this.managedScopes = managedScopes; + this.managedScopesSourceHints = managedScopesSourceHints; + this.managedOptionals = managedOptionals; + this.managedOptionalsSourceHints = managedOptionalsSourceHints; + this.managedLocalPaths = managedLocalPaths; + this.managedLocalPathsSourceHints = managedLocalPathsSourceHints; + this.managedExclusions = managedExclusions; + this.managedExclusionsSourceHints = managedExclusionsSourceHints; + } + + public DependencyManager deriveChildManager( final DependencyCollectionContext context ) + { + Map versions = this.managedVersions; + Map versionsSourceHints = this.managedVersionsSourceHints; + Map scopes = this.managedScopes; + Map scopesSourceHints = this.managedScopesSourceHints; + Map optionals = this.managedOptionals; + Map optionalsSourceHints = this.managedOptionalsSourceHints; + Map localPaths = this.managedLocalPaths; + Map localPathsSourceHints = this.managedLocalPathsSourceHints; + Map> exclusions = this.managedExclusions; + Map> exclusionsSourceHints = this.managedExclusionsSourceHints; + + for ( Dependency managedDependency : context.getManagedDependencies() ) + { + Artifact artifact = managedDependency.getArtifact(); + Object key = getKey( artifact ); + + String version = artifact.getVersion(); + if ( version.length() > 0 && !versions.containsKey( key ) ) + { + if ( versions == this.managedVersions ) + { + versions = new HashMap( this.managedVersions ); + versionsSourceHints = new HashMap( this.managedVersionsSourceHints ); + } + versions.put( key, version ); + versionsSourceHints.put( key, managedDependency.getSourceHint() ); + } + + String scope = managedDependency.getScope(); + if ( scope.length() > 0 && !scopes.containsKey( key ) ) + { + if ( scopes == this.managedScopes ) + { + scopes = new HashMap( this.managedScopes ); + scopesSourceHints = new HashMap( this.managedScopesSourceHints ); + } + scopes.put( key, scope ); + scopesSourceHints.put( key, managedDependency.getSourceHint() ); + } + + Boolean optional = managedDependency.getOptional(); + if ( optional != null && !optionals.containsKey( key ) ) + { + if ( optionals == this.managedOptionals ) + { + optionals = new HashMap( this.managedOptionals ); + optionalsSourceHints = new HashMap( this.managedOptionalsSourceHints ); + } + optionals.put( key, optional ); + optionalsSourceHints.put( key, managedDependency.getSourceHint() ); + } + + String localPath = managedDependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ); + if ( localPath != null && !localPaths.containsKey( key ) ) + { + if ( localPaths == this.managedLocalPaths ) + { + localPaths = new HashMap( this.managedLocalPaths ); + localPathsSourceHints = new HashMap( this.managedLocalPathsSourceHints ); + } + localPaths.put( key, localPath ); + localPathsSourceHints.put( key, managedDependency.getSourceHint() ); + } + + if ( !managedDependency.getExclusions().isEmpty() ) + { + if ( exclusions == this.managedExclusions ) + { + exclusions = new HashMap>( this.managedExclusions ); + exclusionsSourceHints = + new HashMap>( this.managedExclusionsSourceHints ); + + } + Collection managed = exclusions.get( key ); + if ( managed == null ) + { + managed = new LinkedHashSet(); + exclusions.put( key, managed ); + } + managed.addAll( managedDependency.getExclusions() ); + + Collection managedSourceHints = exclusionsSourceHints.get( key ); + if ( managedSourceHints == null ) + { + managedSourceHints = new LinkedHashSet(); + exclusionsSourceHints.put( key, managedSourceHints ); + } + + managedSourceHints.add( managedDependency.getSourceHint() ); + } + } + + return new TransitiveDependencyManager( depth + 1, + versions, versionsSourceHints, + scopes, scopesSourceHints, + optionals, optionalsSourceHints, + localPaths, localPathsSourceHints, + exclusions, exclusionsSourceHints ); + + } + + public DependencyManagement manageDependency( Dependency dependency ) + { + DependencyManagement management = null; + + Object key = getKey( dependency.getArtifact() ); + + if ( this.depth >= 2 ) + { + String version = managedVersions.get( key ); + if ( version != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + management.setVersion( version ); + management.setVersionSourceHint( this.managedVersionsSourceHints.get( key ) ); + } + + String scope = managedScopes.get( key ); + if ( scope != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + management.setScope( scope ); + management.setScopeSourceHint( this.managedScopesSourceHints.get( key ) ); + + if ( !JavaScopes.SYSTEM.equals( scope ) + && dependency.getArtifact().getProperty( ArtifactProperties.LOCAL_PATH, null ) != null ) + { + Map properties = + new HashMap( dependency.getArtifact().getProperties() ); + properties.remove( ArtifactProperties.LOCAL_PATH ); + management.setProperties( properties ); + management.setPropertiesSourceHint( this.managedScopesSourceHints.get( key ) ); + } + } + + if ( ( scope != null && JavaScopes.SYSTEM.equals( scope ) ) + || ( scope == null && JavaScopes.SYSTEM.equals( dependency.getScope() ) ) ) + { + String localPath = managedLocalPaths.get( key ); + if ( localPath != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + Map properties = + new HashMap( dependency.getArtifact().getProperties() ); + properties.put( ArtifactProperties.LOCAL_PATH, localPath ); + management.setProperties( properties ); + management.setPropertiesSourceHint( this.managedLocalPathsSourceHints.get( key ) ); + } + } + + Boolean optional = managedOptionals.get( key ); + if ( optional != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + management.setOptional( optional ); + management.setOptionalitySourceHint( this.managedOptionalsSourceHints.get( key ) ); + } + } + + Collection exclusions = managedExclusions.get( key ); + if ( exclusions != null ) + { + if ( management == null ) + { + management = new DependencyManagement(); + } + Collection result = new LinkedHashSet( dependency.getExclusions() ); + result.addAll( exclusions ); + management.setExclusions( result ); + + final Object sourceHint = this.managedExclusionsSourceHints.get( key ); + if ( sourceHint != null ) + { + management.setExclusionsSourceHint( sourceHint.toString() ); + } + } + + return management; + } + + private Object getKey( Artifact a ) + { + return new Key( a ); + } + + @Override + public boolean equals( final Object obj ) + { + boolean equal = obj instanceof TransitiveDependencyManager; + + if ( equal ) + { + final TransitiveDependencyManager that = (TransitiveDependencyManager) obj; + return this.depth == that.depth + && this.managedVersions.equals( that.managedVersions ) + && this.managedScopes.equals( that.managedScopes ) + && this.managedOptionals.equals( that.managedOptionals ) + && this.managedExclusions.equals( that.managedExclusions ); + + } + + return equal; + } + + @Override + public int hashCode() + { + if ( this.hashCode == 0 ) + { + int hash = 17; + hash = hash * 31 + this.depth; + hash = hash * 31 + this.managedVersions.hashCode(); + hash = hash * 31 + this.managedScopes.hashCode(); + hash = hash * 31 + this.managedOptionals.hashCode(); + hash = hash * 31 + this.managedExclusions.hashCode(); + this.hashCode = hash; + } + return this.hashCode; + } + + static class Key + { + + private final Artifact artifact; + + private final int hashCode; + + Key( final Artifact artifact ) + { + this.artifact = artifact; + + int hash = 17; + hash = hash * 31 + artifact.getGroupId().hashCode(); + hash = hash * 31 + artifact.getArtifactId().hashCode(); + this.hashCode = hash; + } + + @Override + public boolean equals( final Object obj ) + { + boolean equal = obj instanceof Key; + + if ( equal ) + { + final Key that = (Key) obj; + return this.artifact.getArtifactId().equals( that.artifact.getArtifactId() ) + && this.artifact.getGroupId().equals( that.artifact.getGroupId() ) + && this.artifact.getExtension().equals( that.artifact.getExtension() ) + && this.artifact.getClassifier().equals( that.artifact.getClassifier() ); + + } + + return equal; + } + + @Override + public int hashCode() + { + return this.hashCode; + } + + } + +} diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java index 552fc0966..92db1417e 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/selector/ScopeDependencySelector.java @@ -8,9 +8,9 @@ * 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 @@ -24,7 +24,6 @@ import java.util.Collection; import java.util.HashSet; import java.util.TreeSet; - import org.eclipse.aether.collection.DependencyCollectionContext; import org.eclipse.aether.collection.DependencySelector; import org.eclipse.aether.graph.Dependency; @@ -33,14 +32,14 @@ * A dependency selector that filters transitive dependencies based on their scope. Direct dependencies are always * included regardless of their scope. Note: This filter does not assume any relationships between the scopes. * In particular, the filter is not aware of scopes that logically include other scopes. - * + * * @see Dependency#getScope() */ public final class ScopeDependencySelector implements DependencySelector { - private final boolean transitive; + private final int depth; private final Collection included; @@ -48,13 +47,14 @@ public final class ScopeDependencySelector /** * Creates a new selector using the specified includes and excludes. - * + * * @param included The set of scopes to include, may be {@code null} or empty to include any scope. * @param excluded The set of scopes to exclude, may be {@code null} or empty to exclude no scope. */ public ScopeDependencySelector( Collection included, Collection excluded ) { - transitive = false; + super(); + this.depth = 0; this.included = clone( included ); this.excluded = clone( excluded ); } @@ -81,7 +81,7 @@ private static Collection clone( Collection scopes ) /** * Creates a new selector using the specified excludes. - * + * * @param excluded The set of scopes to exclude, may be {@code null} or empty to exclude no scope. */ public ScopeDependencySelector( String... excluded ) @@ -89,32 +89,28 @@ public ScopeDependencySelector( String... excluded ) this( null, ( excluded != null ) ? Arrays.asList( excluded ) : null ); } - private ScopeDependencySelector( boolean transitive, Collection included, Collection excluded ) + private ScopeDependencySelector( int depth, Collection included, Collection excluded ) { - this.transitive = transitive; + super(); + this.depth = depth; this.included = included; this.excluded = excluded; } public boolean selectDependency( Dependency dependency ) { - if ( !transitive ) - { - return true; - } + return this.depth < 2 + || ( ( included == null || included.contains( dependency.getScope() ) ) + && ( excluded == null || !excluded.contains( dependency.getScope() ) ) ); - String scope = dependency.getScope(); - return ( included == null || included.contains( scope ) ) && ( excluded == null || !excluded.contains( scope ) ); } public DependencySelector deriveChildSelector( DependencyCollectionContext context ) { - if ( this.transitive || context.getDependency() == null ) - { - return this; - } + return this.depth >= 2 + ? this + : new ScopeDependencySelector( this.depth + 1, this.included, this.excluded ); - return new ScopeDependencySelector( true, included, excluded ); } @Override @@ -130,7 +126,7 @@ else if ( null == obj || !getClass().equals( obj.getClass() ) ) } ScopeDependencySelector that = (ScopeDependencySelector) obj; - return transitive == that.transitive && eq( included, that.included ) && eq( excluded, that.excluded ); + return this.depth == that.depth && eq( included, that.included ) && eq( excluded, that.excluded ); } private static boolean eq( T o1, T o2 ) @@ -142,7 +138,7 @@ private static boolean eq( T o1, T o2 ) public int hashCode() { int hash = 17; - hash = hash * 31 + ( transitive ? 1 : 0 ); + hash = hash * 31 + this.depth; hash = hash * 31 + ( included != null ? included.hashCode() : 0 ); hash = hash * 31 + ( excluded != null ? excluded.hashCode() : 0 ); return hash; diff --git a/pom.xml b/pom.xml index 3b849a7c6..721cde9b1 100644 --- a/pom.xml +++ b/pom.xml @@ -30,7 +30,7 @@ org.apache.maven.resolver maven-resolver - 1.1.2-SNAPSHOT + 1.2.0-SNAPSHOT pom Maven Artifact Resolver