From 9b515ad3448085236fc1cafe2144d2d54a7f0798 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 20 Dec 2023 00:03:54 +0100 Subject: [PATCH 1/7] [MRESOLVER-461] Cleanup in dep managers 3 of them were almost same. --- https://issues.apache.org/jira/browse/MRESOLVER-461 --- .../manager/AbstractDependencyManager.java | 294 ++++++++++++++++++ .../manager/ClassicDependencyManager.java | 260 ++-------------- .../manager/DefaultDependencyManager.java | 255 ++------------- .../manager/TransitiveDependencyManager.java | 259 ++------------- 4 files changed, 394 insertions(+), 674 deletions(-) create mode 100644 maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java new file mode 100644 index 000000000..dd3ad242c --- /dev/null +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java @@ -0,0 +1,294 @@ +/* + * 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. + */ +package org.eclipse.aether.util.graph.manager; + +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashSet; +import java.util.Map; +import java.util.Objects; + +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; + +import static java.util.Objects.requireNonNull; + +/** + * A dependency manager support class. + * + * @since 2.0.0 + */ +public abstract class AbstractDependencyManager implements DependencyManager { + + protected final int depth; + + protected final int deriveUntil; + + protected final int applyFrom; + + protected final Map managedVersions; + + protected final Map managedScopes; + + protected final Map managedOptionals; + + protected final Map managedLocalPaths; + + protected final Map> managedExclusions; + + private final int hashCode; + + /** + * Creates a new dependency manager without any management information. + */ + protected AbstractDependencyManager(int deriveUntil, int applyFrom) { + this( + 0, + deriveUntil, + applyFrom, + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyMap(), + Collections.emptyMap()); + } + + protected AbstractDependencyManager( + int depth, + int deriveUntil, + int applyFrom, + Map managedVersions, + Map managedScopes, + Map managedOptionals, + Map managedLocalPaths, + Map> managedExclusions) { + this.depth = depth; + this.deriveUntil = deriveUntil; + this.applyFrom = applyFrom; + this.managedVersions = managedVersions; + this.managedScopes = managedScopes; + this.managedOptionals = managedOptionals; + this.managedLocalPaths = managedLocalPaths; + this.managedExclusions = managedExclusions; + + this.hashCode = Objects.hash( + depth, + deriveUntil, + applyFrom, + managedVersions, + managedScopes, + managedOptionals, + managedLocalPaths, + managedExclusions); + } + + protected abstract DependencyManager newInstance( + Map managedVersions, + Map managedScopes, + Map managedOptionals, + Map managedLocalPaths, + Map> managedExclusions); + + @Override + public DependencyManager deriveChildManager(DependencyCollectionContext context) { + if (depth >= deriveUntil) { + return this; + } + Map managedVersions = this.managedVersions; + Map managedScopes = this.managedScopes; + Map managedOptionals = this.managedOptionals; + Map managedLocalPaths = this.managedLocalPaths; + Map> managedExclusions = this.managedExclusions; + + for (Dependency managedDependency : context.getManagedDependencies()) { + Artifact artifact = managedDependency.getArtifact(); + Object key = new Key(artifact); + + String version = artifact.getVersion(); + if (!version.isEmpty() && !managedVersions.containsKey(key)) { + if (managedVersions == this.managedVersions) { + managedVersions = new HashMap<>(this.managedVersions); + } + managedVersions.put(key, version); + } + + String scope = managedDependency.getScope(); + if (!scope.isEmpty() && !managedScopes.containsKey(key)) { + if (managedScopes == this.managedScopes) { + managedScopes = new HashMap<>(this.managedScopes); + } + managedScopes.put(key, scope); + } + + Boolean optional = managedDependency.getOptional(); + if (optional != null && !managedOptionals.containsKey(key)) { + if (managedOptionals == this.managedOptionals) { + managedOptionals = new HashMap<>(this.managedOptionals); + } + managedOptionals.put(key, optional); + } + + String localPath = managedDependency.getArtifact().getProperty(ArtifactProperties.LOCAL_PATH, null); + if (localPath != null && !managedLocalPaths.containsKey(key)) { + if (managedLocalPaths == this.managedLocalPaths) { + managedLocalPaths = new HashMap<>(this.managedLocalPaths); + } + managedLocalPaths.put(key, localPath); + } + + Collection exclusions = managedDependency.getExclusions(); + if (!exclusions.isEmpty()) { + if (managedExclusions == this.managedExclusions) { + managedExclusions = new HashMap<>(this.managedExclusions); + } + Collection managed = managedExclusions.computeIfAbsent(key, k -> new LinkedHashSet<>()); + managed.addAll(exclusions); + } + } + + return newInstance(managedVersions, managedScopes, managedOptionals, managedLocalPaths, managedExclusions); + } + + @Override + public DependencyManagement manageDependency(Dependency dependency) { + requireNonNull(dependency, "dependency cannot be null"); + DependencyManagement management = null; + + Object key = new Key(dependency.getArtifact()); + + if (depth >= applyFrom) { + String version = managedVersions.get(key); + if (version != null) { + management = new DependencyManagement(); + management.setVersion(version); + } + + String scope = managedScopes.get(key); + if (scope != null) { + if (management == null) { + management = new DependencyManagement(); + } + management.setScope(scope); + + 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); + } + } + + if ((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); + } + } + + Boolean optional = managedOptionals.get(key); + if (optional != null) { + if (management == null) { + management = new DependencyManagement(); + } + management.setOptional(optional); + } + } + + 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); + } + + return management; + } + + @Override + public boolean equals(Object obj) { + if (this == obj) { + return true; + } else if (null == obj || !getClass().equals(obj.getClass())) { + return false; + } + + AbstractDependencyManager that = (AbstractDependencyManager) obj; + return depth == that.depth + && deriveUntil == that.deriveUntil + && applyFrom == that.applyFrom + && managedVersions.equals(that.managedVersions) + && managedScopes.equals(that.managedScopes) + && managedOptionals.equals(that.managedOptionals) + && managedExclusions.equals(that.managedExclusions); + } + + @Override + public int hashCode() { + return hashCode; + } + + protected static class Key { + + private final Artifact artifact; + + private final int hashCode; + + Key(Artifact artifact) { + this.artifact = artifact; + this.hashCode = Objects.hash(artifact.getGroupId(), artifact.getArtifactId()); + } + + @Override + public boolean equals(Object obj) { + if (obj == this) { + return true; + } else if (!(obj instanceof Key)) { + return false; + } + 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()); + } + + @Override + public int hashCode() { + return hashCode; + } + } +} 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 199173762..681cc5521 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 @@ -19,265 +19,69 @@ package org.eclipse.aether.util.graph.manager; 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; import static java.util.Objects.requireNonNull; /** * A dependency manager that mimics the way Maven 2.x works. */ -public final class ClassicDependencyManager implements DependencyManager { - - private final int depth; - - private final Map managedVersions; - - private final Map managedScopes; - - private final Map managedOptionals; - - private final Map managedLocalPaths; - - private final Map> managedExclusions; - - private int hashCode; - +public final class ClassicDependencyManager extends AbstractDependencyManager { /** * Creates a new dependency manager without any management information. */ public ClassicDependencyManager() { - this( - 0, - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.>emptyMap()); + super(2, 2); } private ClassicDependencyManager( int depth, + int deriveUntil, + int applyFrom, Map managedVersions, Map managedScopes, Map managedOptionals, Map managedLocalPaths, Map> managedExclusions) { - this.depth = depth; - this.managedVersions = managedVersions; - this.managedScopes = managedScopes; - this.managedOptionals = managedOptionals; - this.managedLocalPaths = managedLocalPaths; - this.managedExclusions = managedExclusions; + super( + depth, + deriveUntil, + applyFrom, + managedVersions, + managedScopes, + managedOptionals, + managedLocalPaths, + managedExclusions); } + @Override public DependencyManager deriveChildManager(DependencyCollectionContext context) { requireNonNull(context, "context cannot be null"); - if (depth >= 2) { - return this; - } else if (depth == 1) { - return new ClassicDependencyManager( - depth + 1, managedVersions, managedScopes, managedOptionals, managedLocalPaths, managedExclusions); - } - - Map managedVersions = this.managedVersions; - Map managedScopes = this.managedScopes; - Map managedOptionals = this.managedOptionals; - Map managedLocalPaths = this.managedLocalPaths; - Map> managedExclusions = this.managedExclusions; - - for (Dependency managedDependency : context.getManagedDependencies()) { - Artifact artifact = managedDependency.getArtifact(); - Object key = getKey(artifact); - - String version = artifact.getVersion(); - if (!version.isEmpty() && !managedVersions.containsKey(key)) { - if (managedVersions == this.managedVersions) { - managedVersions = new HashMap<>(this.managedVersions); - } - managedVersions.put(key, version); - } - - String scope = managedDependency.getScope(); - if (!scope.isEmpty() && !managedScopes.containsKey(key)) { - if (managedScopes == this.managedScopes) { - managedScopes = new HashMap<>(this.managedScopes); - } - managedScopes.put(key, scope); - } - - Boolean optional = managedDependency.getOptional(); - if (optional != null && !managedOptionals.containsKey(key)) { - if (managedOptionals == this.managedOptionals) { - managedOptionals = new HashMap<>(this.managedOptionals); - } - managedOptionals.put(key, optional); - } - - String localPath = managedDependency.getArtifact().getProperty(ArtifactProperties.LOCAL_PATH, null); - if (localPath != null && !managedLocalPaths.containsKey(key)) { - if (managedLocalPaths == this.managedLocalPaths) { - managedLocalPaths = new HashMap<>(this.managedLocalPaths); - } - managedLocalPaths.put(key, localPath); - } - - Collection exclusions = managedDependency.getExclusions(); - if (!exclusions.isEmpty()) { - if (managedExclusions == this.managedExclusions) { - managedExclusions = new HashMap<>(this.managedExclusions); - } - Collection managed = managedExclusions.computeIfAbsent(key, k -> new LinkedHashSet<>()); - managed.addAll(exclusions); - } - } - - return new ClassicDependencyManager( - depth + 1, managedVersions, managedScopes, managedOptionals, managedLocalPaths, managedExclusions); - } - - public DependencyManagement manageDependency(Dependency dependency) { - requireNonNull(dependency, "dependency cannot be null"); - DependencyManagement management = null; - - Object key = getKey(dependency.getArtifact()); - - if (depth >= 2) { - String version = managedVersions.get(key); - if (version != null) { - management = new DependencyManagement(); - management.setVersion(version); - } - - String scope = managedScopes.get(key); - if (scope != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setScope(scope); - - 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); - } - } - - if ((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); - } - } - - Boolean optional = managedOptionals.get(key); - if (optional != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setOptional(optional); - } + if (depth == 1) { + return newInstance(managedVersions, managedScopes, managedOptionals, managedLocalPaths, managedExclusions); } - - 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); - } - - return management; - } - - private Object getKey(Artifact a) { - return new Key(a); - } - - @Override - public boolean equals(Object obj) { - if (this == obj) { - return true; - } else if (null == obj || !getClass().equals(obj.getClass())) { - return false; - } - - ClassicDependencyManager that = (ClassicDependencyManager) obj; - return depth == that.depth - && managedVersions.equals(that.managedVersions) - && managedScopes.equals(that.managedScopes) - && managedOptionals.equals(that.managedOptionals) - && managedExclusions.equals(that.managedExclusions); + return super.deriveChildManager(context); } @Override - public int hashCode() { - if (hashCode == 0) { - int hash = 17; - hash = hash * 31 + depth; - hash = hash * 31 + managedVersions.hashCode(); - hash = hash * 31 + managedScopes.hashCode(); - hash = hash * 31 + managedOptionals.hashCode(); - hash = hash * 31 + managedExclusions.hashCode(); - hashCode = hash; - } - return hashCode; - } - - static class Key { - - private final Artifact artifact; - - private final int hashCode; - - Key(Artifact artifact) { - this.artifact = artifact; - - int hash = 17; - hash = hash * 31 + artifact.getGroupId().hashCode(); - hash = hash * 31 + artifact.getArtifactId().hashCode(); - hashCode = hash; - } - - @Override - public boolean equals(Object obj) { - if (obj == this) { - return true; - } else if (!(obj instanceof Key)) { - return false; - } - 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()); - } - - @Override - public int hashCode() { - return hashCode; - } + protected DependencyManager newInstance( + Map managedVersions, + Map managedScopes, + Map managedOptionals, + Map managedLocalPaths, + Map> managedExclusions) { + return new ClassicDependencyManager( + depth + 1, + deriveUntil, + applyFrom, + managedVersions, + managedScopes, + managedOptionals, + managedLocalPaths, + managedExclusions); } } 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 index 332a36227..23765012a 100644 --- 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 @@ -19,22 +19,10 @@ package org.eclipse.aether.util.graph.manager; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.Map; -import java.util.Objects; -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; - -import static java.util.Objects.requireNonNull; /** * A dependency manager managing dependencies on all levels supporting transitive dependency management. @@ -47,224 +35,49 @@ * @author Christian Schulte * @since 1.4.0 */ -public final class DefaultDependencyManager implements DependencyManager { - - private final Map managedVersions; - - private final Map managedScopes; - - private final Map managedOptionals; - - private final Map managedLocalPaths; - - private final Map> managedExclusions; - - private int hashCode; - +public final class DefaultDependencyManager extends AbstractDependencyManager { /** * Creates a new dependency manager without any management information. */ public DefaultDependencyManager() { - this( - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.>emptyMap()); + super(Integer.MAX_VALUE, 0); } private DefaultDependencyManager( - final Map managedVersions, - final Map managedScopes, - final Map managedOptionals, - final Map managedLocalPaths, - final Map> managedExclusions) { - super(); - this.managedVersions = managedVersions; - this.managedScopes = managedScopes; - this.managedOptionals = managedOptionals; - this.managedLocalPaths = managedLocalPaths; - this.managedExclusions = managedExclusions; - } - - public DependencyManager deriveChildManager(final DependencyCollectionContext context) { - requireNonNull(context, "context cannot be null"); - Map versions = this.managedVersions; - Map scopes = this.managedScopes; - Map optionals = this.managedOptionals; - Map localPaths = this.managedLocalPaths; - Map> exclusions = this.managedExclusions; - - for (Dependency managedDependency : context.getManagedDependencies()) { - Artifact artifact = managedDependency.getArtifact(); - Object key = getKey(artifact); - - String version = artifact.getVersion(); - if (!version.isEmpty() && !versions.containsKey(key)) { - if (versions == this.managedVersions) { - versions = new HashMap<>(this.managedVersions); - } - versions.put(key, version); - } - - String scope = managedDependency.getScope(); - if (!scope.isEmpty() && !scopes.containsKey(key)) { - if (scopes == this.managedScopes) { - scopes = new HashMap<>(this.managedScopes); - } - scopes.put(key, scope); - } - - Boolean optional = managedDependency.getOptional(); - if (optional != null && !optionals.containsKey(key)) { - if (optionals == this.managedOptionals) { - optionals = new HashMap<>(this.managedOptionals); - } - optionals.put(key, optional); - } - - String localPath = managedDependency.getArtifact().getProperty(ArtifactProperties.LOCAL_PATH, null); - if (localPath != null && !localPaths.containsKey(key)) { - if (localPaths == this.managedLocalPaths) { - localPaths = new HashMap<>(this.managedLocalPaths); - } - localPaths.put(key, localPath); - } - - if (!managedDependency.getExclusions().isEmpty()) { - if (exclusions == this.managedExclusions) { - exclusions = new HashMap<>(this.managedExclusions); - } - Collection managed = exclusions.computeIfAbsent(key, k -> new LinkedHashSet<>()); - managed.addAll(managedDependency.getExclusions()); - } - } - - return new DefaultDependencyManager(versions, scopes, optionals, localPaths, exclusions); - } - - public DependencyManagement manageDependency(Dependency dependency) { - requireNonNull(dependency, "dependency cannot be null"); - DependencyManagement management = null; - - Object key = getKey(dependency.getArtifact()); - - String version = managedVersions.get(key); - if (version != null) { - management = new DependencyManagement(); - management.setVersion(version); - } - - String scope = managedScopes.get(key); - if (scope != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setScope(scope); - - 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); - } - } - - 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); - } - } - - Boolean optional = managedOptionals.get(key); - if (optional != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setOptional(optional); - } - - 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); - } - - return management; - } - - private Object getKey(Artifact a) { - return new Key(a); + int depth, + int deriveUntil, + int applyFrom, + Map managedVersions, + Map managedScopes, + Map managedOptionals, + Map managedLocalPaths, + Map> managedExclusions) { + super( + depth, + deriveUntil, + applyFrom, + managedVersions, + managedScopes, + managedOptionals, + managedLocalPaths, + managedExclusions); } @Override - public boolean equals(final Object obj) { - boolean equal = obj instanceof DefaultDependencyManager; - - if (equal) { - final DefaultDependencyManager that = (DefaultDependencyManager) obj; - equal = Objects.equals(managedVersions, that.managedVersions) - && Objects.equals(managedScopes, that.managedScopes) - && Objects.equals(managedOptionals, that.managedOptionals) - && Objects.equals(managedExclusions, that.managedExclusions); - } - - return equal; - } - - @Override - public int hashCode() { - if (hashCode == 0) { - hashCode = Objects.hash(managedVersions, managedScopes, managedOptionals, managedExclusions); - } - return hashCode; - } - - static class Key { - - private final Artifact artifact; - - private final int hashCode; - - Key(final Artifact artifact) { - this.artifact = artifact; - this.hashCode = Objects.hash(artifact.getGroupId(), artifact.getArtifactId()); - } - - @Override - public boolean equals(final Object obj) { - boolean equal = obj instanceof Key; - - if (equal) { - final Key that = (Key) obj; - return Objects.equals(artifact.getArtifactId(), that.artifact.getArtifactId()) - && Objects.equals(artifact.getGroupId(), that.artifact.getGroupId()) - && Objects.equals(artifact.getExtension(), that.artifact.getExtension()) - && Objects.equals(artifact.getClassifier(), that.artifact.getClassifier()); - } - - return false; - } - - @Override - public int hashCode() { - return this.hashCode; - } + protected DependencyManager newInstance( + Map managedVersions, + Map managedScopes, + Map managedOptionals, + Map managedLocalPaths, + Map> managedExclusions) { + return new DefaultDependencyManager( + depth + 1, + deriveUntil, + applyFrom, + managedVersions, + managedScopes, + managedOptionals, + managedLocalPaths, + managedExclusions); } } 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 index 9e6912390..d1933197c 100644 --- 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 @@ -19,22 +19,10 @@ package org.eclipse.aether.util.graph.manager; import java.util.Collection; -import java.util.Collections; -import java.util.HashMap; -import java.util.LinkedHashSet; import java.util.Map; -import java.util.Objects; -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; - -import static java.util.Objects.requireNonNull; /** * A dependency manager managing transitive dependencies supporting transitive dependency management. @@ -42,228 +30,49 @@ * @author Christian Schulte * @since 1.4.0 */ -public final class TransitiveDependencyManager implements DependencyManager { - - private final Map managedVersions; - - private final Map managedScopes; - - private final Map managedOptionals; - - private final Map managedLocalPaths; - - private final Map> managedExclusions; - - private final int depth; - - private int hashCode; - +public final class TransitiveDependencyManager extends AbstractDependencyManager { /** * Creates a new dependency manager without any management information. */ public TransitiveDependencyManager() { - this( - 0, - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.emptyMap(), - Collections.>emptyMap()); + super(Integer.MAX_VALUE, 2); } private TransitiveDependencyManager( - final int depth, - final Map managedVersions, - final Map managedScopes, - final Map managedOptionals, - final Map managedLocalPaths, - final Map> managedExclusions) { - super(); - this.depth = depth; - this.managedVersions = managedVersions; - this.managedScopes = managedScopes; - this.managedOptionals = managedOptionals; - this.managedLocalPaths = managedLocalPaths; - this.managedExclusions = managedExclusions; - } - - public DependencyManager deriveChildManager(final DependencyCollectionContext context) { - requireNonNull(context, "context cannot be null"); - Map versions = managedVersions; - Map scopes = managedScopes; - Map optionals = managedOptionals; - Map localPaths = managedLocalPaths; - Map> exclusions = managedExclusions; - - for (Dependency managedDependency : context.getManagedDependencies()) { - Artifact artifact = managedDependency.getArtifact(); - Object key = getKey(artifact); - - String version = artifact.getVersion(); - if (!version.isEmpty() && !versions.containsKey(key)) { - if (versions == managedVersions) { - versions = new HashMap<>(managedVersions); - } - versions.put(key, version); - } - - String scope = managedDependency.getScope(); - if (!scope.isEmpty() && !scopes.containsKey(key)) { - if (scopes == this.managedScopes) { - scopes = new HashMap<>(this.managedScopes); - } - scopes.put(key, scope); - } - - Boolean optional = managedDependency.getOptional(); - if (optional != null && !optionals.containsKey(key)) { - if (optionals == managedOptionals) { - optionals = new HashMap<>(managedOptionals); - } - optionals.put(key, optional); - } - - String localPath = managedDependency.getArtifact().getProperty(ArtifactProperties.LOCAL_PATH, null); - if (localPath != null && !localPaths.containsKey(key)) { - if (localPaths == this.managedLocalPaths) { - localPaths = new HashMap<>(managedLocalPaths); - } - localPaths.put(key, localPath); - } - - if (!managedDependency.getExclusions().isEmpty()) { - if (exclusions == managedExclusions) { - exclusions = new HashMap<>(managedExclusions); - } - Collection managed = exclusions.computeIfAbsent(key, k -> new LinkedHashSet<>()); - managed.addAll(managedDependency.getExclusions()); - } - } - - return new TransitiveDependencyManager(depth + 1, versions, scopes, optionals, localPaths, exclusions); - } - - public DependencyManagement manageDependency(Dependency dependency) { - requireNonNull(dependency, "dependency cannot be null"); - DependencyManagement management = null; - - Object key = getKey(dependency.getArtifact()); - - if (depth >= 2) { - String version = managedVersions.get(key); - if (version != null) { - management = new DependencyManagement(); - management.setVersion(version); - } - - String scope = managedScopes.get(key); - if (scope != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setScope(scope); - - 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); - } - } - - if ((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); - } - } - - Boolean optional = managedOptionals.get(key); - if (optional != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setOptional(optional); - } - } - - 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); - } - - return management; - } - - private Object getKey(Artifact a) { - return new Key(a); + int depth, + int deriveUntil, + int applyFrom, + Map managedVersions, + Map managedScopes, + Map managedOptionals, + Map managedLocalPaths, + Map> managedExclusions) { + super( + depth, + deriveUntil, + applyFrom, + managedVersions, + managedScopes, + managedOptionals, + managedLocalPaths, + managedExclusions); } @Override - public boolean equals(final Object obj) { - boolean equal = obj instanceof TransitiveDependencyManager; - - if (equal) { - final TransitiveDependencyManager that = (TransitiveDependencyManager) obj; - return depth == that.depth - && Objects.equals(managedVersions, that.managedVersions) - && Objects.equals(managedScopes, that.managedScopes) - && Objects.equals(managedOptionals, that.managedOptionals) - && Objects.equals(managedExclusions, that.managedExclusions); - } - - return false; - } - - @Override - public int hashCode() { - if (hashCode == 0) { - hashCode = Objects.hash(depth, managedVersions, managedScopes, managedOptionals, managedExclusions); - } - return hashCode; - } - - static class Key { - private final Artifact artifact; - - private final int hashCode; - - Key(final Artifact artifact) { - this.artifact = artifact; - this.hashCode = Objects.hash(artifact.getGroupId(), artifact.getArtifactId()); - } - - @Override - public boolean equals(final Object obj) { - boolean equal = obj instanceof Key; - - if (equal) { - final Key that = (Key) obj; - return Objects.equals(artifact.getArtifactId(), that.artifact.getArtifactId()) - && Objects.equals(artifact.getGroupId(), that.artifact.getGroupId()) - && Objects.equals(artifact.getExtension(), that.artifact.getExtension()) - && Objects.equals(artifact.getClassifier(), that.artifact.getClassifier()); - } - - return false; - } - - @Override - public int hashCode() { - return this.hashCode; - } + protected DependencyManager newInstance( + Map managedVersions, + Map managedScopes, + Map managedOptionals, + Map managedLocalPaths, + Map> managedExclusions) { + return new TransitiveDependencyManager( + depth + 1, + deriveUntil, + applyFrom, + managedVersions, + managedScopes, + managedOptionals, + managedLocalPaths, + managedExclusions); } } From 323f1e7140f1d4941db7a3d925ff0d7f5bfb1541 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 20 Dec 2023 00:09:42 +0100 Subject: [PATCH 2/7] Fix checkstyle failures --- .../aether/util/graph/manager/AbstractDependencyManager.java | 1 + .../aether/util/graph/manager/ClassicDependencyManager.java | 1 + .../aether/util/graph/manager/DefaultDependencyManager.java | 1 + .../aether/util/graph/manager/TransitiveDependencyManager.java | 1 + 4 files changed, 4 insertions(+) diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java index dd3ad242c..45e0523d6 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java @@ -76,6 +76,7 @@ protected AbstractDependencyManager(int deriveUntil, int applyFrom) { Collections.emptyMap()); } + @SuppressWarnings("checkstyle:ParameterNumber") protected AbstractDependencyManager( int depth, int deriveUntil, 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 681cc5521..fa0d723ad 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 @@ -38,6 +38,7 @@ public ClassicDependencyManager() { super(2, 2); } + @SuppressWarnings("checkstyle:ParameterNumber") private ClassicDependencyManager( int depth, int deriveUntil, 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 index 23765012a..1390bebf0 100644 --- 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 @@ -43,6 +43,7 @@ public DefaultDependencyManager() { super(Integer.MAX_VALUE, 0); } + @SuppressWarnings("checkstyle:ParameterNumber") private DefaultDependencyManager( int depth, int deriveUntil, 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 index d1933197c..113526aac 100644 --- 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 @@ -38,6 +38,7 @@ public TransitiveDependencyManager() { super(Integer.MAX_VALUE, 2); } + @SuppressWarnings("checkstyle:ParameterNumber") private TransitiveDependencyManager( int depth, int deriveUntil, From b7ae077ee4786ad230f7de946e9eed8e415b58cd Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 20 Dec 2023 00:21:17 +0100 Subject: [PATCH 3/7] Tidy up --- .../aether/util/graph/manager/AbstractDependencyManager.java | 3 ++- .../aether/util/graph/manager/ClassicDependencyManager.java | 1 - 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java index 45e0523d6..5cf7ebb3c 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/manager/AbstractDependencyManager.java @@ -115,9 +115,11 @@ protected abstract DependencyManager newInstance( @Override public DependencyManager deriveChildManager(DependencyCollectionContext context) { + requireNonNull(context, "context cannot be null"); if (depth >= deriveUntil) { return this; } + Map managedVersions = this.managedVersions; Map managedScopes = this.managedScopes; Map managedOptionals = this.managedOptionals; @@ -177,7 +179,6 @@ public DependencyManager deriveChildManager(DependencyCollectionContext context) public DependencyManagement manageDependency(Dependency dependency) { requireNonNull(dependency, "dependency cannot be null"); DependencyManagement management = null; - Object key = new Key(dependency.getArtifact()); if (depth >= applyFrom) { 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 fa0d723ad..4ac9f2fa7 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 @@ -61,7 +61,6 @@ private ClassicDependencyManager( @Override public DependencyManager deriveChildManager(DependencyCollectionContext context) { - requireNonNull(context, "context cannot be null"); if (depth == 1) { return newInstance(managedVersions, managedScopes, managedOptionals, managedLocalPaths, managedExclusions); } From 06804bdcfe9a2db4361970bab9200036616d6744 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 20 Dec 2023 00:23:17 +0100 Subject: [PATCH 4/7] Reformat --- .../aether/util/graph/manager/ClassicDependencyManager.java | 2 -- 1 file changed, 2 deletions(-) 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 4ac9f2fa7..95265287d 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 @@ -25,8 +25,6 @@ import org.eclipse.aether.collection.DependencyManager; import org.eclipse.aether.graph.Exclusion; -import static java.util.Objects.requireNonNull; - /** * A dependency manager that mimics the way Maven 2.x works. */ From 9343381d385f65f9959bf270b98194eced9b03f0 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 20 Dec 2023 10:23:29 +0100 Subject: [PATCH 5/7] Explain in Javadoc the differences. --- .../aether/util/graph/manager/ClassicDependencyManager.java | 4 +++- .../aether/util/graph/manager/DefaultDependencyManager.java | 3 ++- .../util/graph/manager/TransitiveDependencyManager.java | 3 +++ 3 files changed, 8 insertions(+), 2 deletions(-) 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 95265287d..fa51eac51 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 @@ -26,7 +26,9 @@ import org.eclipse.aether.graph.Exclusion; /** - * A dependency manager that mimics the way Maven 2.x works. + * A dependency manager that mimics the way Maven 2.x works. This manager was used throughout all Maven 3.x versions. + *

+ * This manager has {@code deriveUntil=2} and {@code applyFrom=2}. */ public final class ClassicDependencyManager extends AbstractDependencyManager { /** 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 index 1390bebf0..f76b2a44a 100644 --- 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 @@ -30,7 +30,8 @@ * Note:Unlike the {@code ClassicDependencyManager} and the {@code TransitiveDependencyManager} this * implementation applies management also on the first level. This is considered the resolver's default behaviour. * It ignores all management overrides supported by the {@code MavenModelBuilder}. - *

+ *

+ * This manager has {@code deriveUntil=Integer.MAX_VALUE} and {@code applyFrom=0}. * * @author Christian Schulte * @since 1.4.0 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 index 113526aac..e1ec33048 100644 --- 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 @@ -26,6 +26,9 @@ /** * A dependency manager managing transitive dependencies supporting transitive dependency management. + *

+ * This manager is similar to "classic", it has {@code deriveUntil=Integer.MAX_VALUE} (unlike 2 as in "classic") and + * {@code applyFrom=2}. * * @author Christian Schulte * @since 1.4.0 From d17ae7ae169f2d720dab542c8150b03696a8ff1b Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 20 Dec 2023 10:49:12 +0100 Subject: [PATCH 6/7] Explain this only difference Is another trick for Maven2 backward compatiblity --- .../aether/util/graph/manager/ClassicDependencyManager.java | 3 +++ 1 file changed, 3 insertions(+) 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 fa51eac51..afde36ed0 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 @@ -61,6 +61,9 @@ private ClassicDependencyManager( @Override public DependencyManager deriveChildManager(DependencyCollectionContext context) { + // MNG-4720: Maven2 backward compatibility + // Removing this IF makes one IT fail here (read comment above): + // https://github.com/apache/maven-integration-testing/blob/b4e8fd52b99a058336f9c7c5ec44fdbc1427759c/core-it-suite/src/test/java/org/apache/maven/it/MavenITmng4720DependencyManagementExclusionMergeTest.java#L67 if (depth == 1) { return newInstance(managedVersions, managedScopes, managedOptionals, managedLocalPaths, managedExclusions); } From 0626ce288e05b62827979e89d02ebb51df95f59f Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 20 Dec 2023 11:58:27 +0100 Subject: [PATCH 7/7] Add UTs --- .../manager/ClassicDependencyManagerTest.java | 75 ------ .../graph/manager/DependencyManagerTest.java | 248 ++++++++++++++++++ 2 files changed, 248 insertions(+), 75 deletions(-) delete mode 100644 maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManagerTest.java create mode 100644 maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManagerTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManagerTest.java deleted file mode 100644 index 2db88c095..000000000 --- a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/ClassicDependencyManagerTest.java +++ /dev/null @@ -1,75 +0,0 @@ -/* - * 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. - */ -package org.eclipse.aether.util.graph.manager; - -import java.util.Arrays; - -import org.eclipse.aether.RepositorySystemSession; -import org.eclipse.aether.artifact.Artifact; -import org.eclipse.aether.artifact.DefaultArtifact; -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.internal.test.util.TestUtils; -import org.junit.jupiter.api.BeforeEach; -import org.junit.jupiter.api.Test; - -import static org.junit.jupiter.api.Assertions.*; - -public class ClassicDependencyManagerTest { - - private final Artifact A = new DefaultArtifact("test", "a", "", ""); - - private final Artifact A1 = new DefaultArtifact("test", "a", "", "1"); - - private final Artifact B = new DefaultArtifact("test", "b", "", ""); - - private final Artifact B1 = new DefaultArtifact("test", "b", "", "1"); - - private RepositorySystemSession session; - - private DependencyCollectionContext newContext(Dependency... managedDependencies) { - return TestUtils.newCollectionContext(session, null, Arrays.asList(managedDependencies)); - } - - @BeforeEach - void setUp() { - session = TestUtils.newSession(); - } - - @Test - void testManageOptional() { - DependencyManager manager = new ClassicDependencyManager(); - - manager = manager.deriveChildManager(newContext(new Dependency(A, null, null), new Dependency(B, null, true))); - DependencyManagement mngt; - mngt = manager.manageDependency(new Dependency(A1, null)); - assertNull(mngt); - mngt = manager.manageDependency(new Dependency(B1, null)); - assertNull(mngt); - - manager = manager.deriveChildManager(newContext()); - mngt = manager.manageDependency(new Dependency(A1, null)); - assertNull(mngt); - mngt = manager.manageDependency(new Dependency(B1, null)); - assertNotNull(mngt); - assertEquals(Boolean.TRUE, mngt.getOptional()); - } -} diff --git a/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java new file mode 100644 index 000000000..f2aab8300 --- /dev/null +++ b/maven-resolver-util/src/test/java/org/eclipse/aether/util/graph/manager/DependencyManagerTest.java @@ -0,0 +1,248 @@ +/* + * 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. + */ +package org.eclipse.aether.util.graph.manager; + +import java.util.Arrays; +import java.util.Collections; + +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.artifact.DefaultArtifact; +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.internal.test.util.TestUtils; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.*; + +/** + * UT for {@link DependencyManager} implementations. + */ +public class DependencyManagerTest { + + private final Artifact A1 = new DefaultArtifact("test", "a", "", "1"); + + private final Artifact A2 = new DefaultArtifact("test", "a", "", "2"); + + private final Artifact B1 = new DefaultArtifact("test", "b", "", "1"); + + private final Artifact C1 = new DefaultArtifact("test", "c", "", "1"); + + private final Artifact D1 = new DefaultArtifact("test", "d", "", "1"); + + private final Artifact E1 = new DefaultArtifact("test", "e", "", "1"); + + private final Artifact E2 = new DefaultArtifact("test", "e", "", "2"); + + private final Exclusion EXCLUSION = new Exclusion("test", "excluded", null, null); + + private RepositorySystemSession session; + + private DependencyCollectionContext newContext(Dependency... managedDependencies) { + return TestUtils.newCollectionContext(session, null, Arrays.asList(managedDependencies)); + } + + @BeforeEach + void setUp() { + session = TestUtils.newSession(); + } + + @Test + void testClassic() { + DependencyManager manager = new ClassicDependencyManager(); + DependencyManagement mngt; + + // depth=1: only exclusion applied, nothing more + manager = manager.deriveChildManager(newContext( + new Dependency(A2, null, null), + new Dependency(B1, null, true), + new Dependency(C1, "newscope", null), + new Dependency(D1, null, null, Collections.singleton(EXCLUSION)))); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNull(mngt); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNull(mngt); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNull(mngt); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNull(mngt); + + // depth=2: all applied + manager = manager.deriveChildManager(newContext()); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), A2.getVersion()); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNotNull(mngt); + assertEquals(Boolean.TRUE, mngt.getOptional()); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNotNull(mngt); + assertEquals(mngt.getScope(), "newscope"); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNull(mngt); + + // depth=3: all existing applied, new depMgt ignored, carried on only what we have so far + manager = manager.deriveChildManager(newContext(new Dependency(E2, null, null))); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), A2.getVersion()); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNotNull(mngt); + assertEquals(Boolean.TRUE, mngt.getOptional()); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNotNull(mngt); + assertEquals(mngt.getScope(), "newscope"); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNull(mngt); + } + + @Test + void testTransitive() { + DependencyManager manager = new TransitiveDependencyManager(); + DependencyManagement mngt; + + // depth=1: only exclusion applied, nothing more + manager = manager.deriveChildManager(newContext( + new Dependency(A2, null, null), + new Dependency(B1, null, true), + new Dependency(C1, "newscope", null), + new Dependency(D1, null, null, Collections.singleton(EXCLUSION)))); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNull(mngt); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNull(mngt); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNull(mngt); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNull(mngt); + + // depth=2: all applied + manager = manager.deriveChildManager(newContext()); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), A2.getVersion()); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNotNull(mngt); + assertEquals(Boolean.TRUE, mngt.getOptional()); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNotNull(mngt); + assertEquals(mngt.getScope(), "newscope"); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNull(mngt); + + // depth=3: all existing applied, new depMgt processed, carried on + manager = manager.deriveChildManager(newContext(new Dependency(E2, null, null))); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), A2.getVersion()); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNotNull(mngt); + assertEquals(Boolean.TRUE, mngt.getOptional()); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNotNull(mngt); + assertEquals(mngt.getScope(), "newscope"); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), E2.getVersion()); + } + + @Test + void testDefault() { + DependencyManager manager = new DefaultDependencyManager(); + DependencyManagement mngt; + + // depth=1: all applied + manager = manager.deriveChildManager(newContext( + new Dependency(A2, null, null), + new Dependency(B1, null, true), + new Dependency(C1, "newscope", null), + new Dependency(D1, null, null, Collections.singleton(EXCLUSION)))); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), A2.getVersion()); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNotNull(mngt); + assertEquals(Boolean.TRUE, mngt.getOptional()); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNotNull(mngt); + assertEquals(mngt.getScope(), "newscope"); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNull(mngt); + + // depth=2: all applied + manager = manager.deriveChildManager(newContext()); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), A2.getVersion()); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNotNull(mngt); + assertEquals(Boolean.TRUE, mngt.getOptional()); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNotNull(mngt); + assertEquals(mngt.getScope(), "newscope"); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNull(mngt); + + // depth=3: all existing applied, new depMgt processed, carried on + manager = manager.deriveChildManager(newContext(new Dependency(E2, null, null))); + mngt = manager.manageDependency(new Dependency(A1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), A2.getVersion()); + mngt = manager.manageDependency(new Dependency(B1, null)); + assertNotNull(mngt); + assertEquals(Boolean.TRUE, mngt.getOptional()); + mngt = manager.manageDependency(new Dependency(C1, null)); + assertNotNull(mngt); + assertEquals(mngt.getScope(), "newscope"); + mngt = manager.manageDependency(new Dependency(D1, null)); + assertNotNull(mngt); + assertEquals(mngt.getExclusions(), Collections.singleton(EXCLUSION)); + mngt = manager.manageDependency(new Dependency(E1, null)); + assertNotNull(mngt); + assertEquals(mngt.getVersion(), E2.getVersion()); + } +}