From 2208dcacd70df3bf17c97b0002a2d5033e6c5f1d Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Wed, 1 Oct 2025 17:46:48 +0200 Subject: [PATCH 01/13] Platform WIP --- .../graph/DependencyManagementRule.java | 124 ++++++++++++++++++ .../eclipse/aether/graph/DependencyNode.java | 10 ++ .../eclipse/aether/spi/platform/Platform.java | 74 +++++++++++ .../aether/spi/platform/PlatformGroup.java | 45 +++++++ .../aether/spi/platform/PlatformManager.java | 38 ++++++ .../aether/spi/platform/package-info.java | 23 ++++ 6 files changed, 314 insertions(+) create mode 100644 maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java create mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java create mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java create mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java create mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java new file mode 100644 index 000000000..dfebd4fac --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java @@ -0,0 +1,124 @@ +/* + * 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.graph; + +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.function.UnaryOperator; + +import static java.util.Objects.requireNonNull; + +/** + * Represents a dependency management rule, a managed value of given attribute. + * + * @since 2.0.13 + */ +public class DependencyManagementRule implements UnaryOperator { + public enum Kind { + VERSION, SCOPE, OPTIONAL, PROPERTIES, EXCLUSIONS + } + + public static ManagedVersion managedVersion(String version, boolean enforcing) { + return new ManagedVersion(version, enforcing); + } + + public static ManagedScope managedScope(String scope, boolean enforcing) { + return new ManagedScope(scope, enforcing); + } + + public static ManagedOptional managedOptional(Boolean optional, boolean enforcing) { + return new ManagedOptional(optional, enforcing); + } + + public static ManagedProperties managedProperties(Map properties, boolean enforcing) { + return new ManagedProperties(properties, enforcing); + } + + public static ManagedExclusions managedExclusions(Collection exclusions, boolean enforcing) { + return new ManagedExclusions(exclusions, enforcing); + } + + private final T value; + + private final Kind kind; + + private final boolean enforcing; + + private final UnaryOperator operator; + + protected DependencyManagementRule(T value, Kind kind, boolean enforcing, UnaryOperator operator) { + this.value = requireNonNull(value); + this.kind = requireNonNull(kind); + this.enforcing = enforcing; + this.operator = requireNonNull(operator); + } + + public T getValue() { + return value; + } + + public Kind getKind() { + return kind; + } + + public boolean isEnforcing() { + return enforcing; + } + + @Override + public Dependency apply(Dependency dependency) { + requireNonNull(dependency); + return operator.apply(dependency); + } + + public static final class ManagedVersion extends DependencyManagementRule { + private ManagedVersion(String value, boolean enforcing) { + super(value, Kind.VERSION, enforcing, d -> d.setArtifact(d.getArtifact().setVersion(value))); + } + } + + public static final class ManagedScope extends DependencyManagementRule { + private ManagedScope(String value, boolean enforcing) { + super(value, Kind.SCOPE, enforcing, d -> d.setScope(value)); + } + } + + public static final class ManagedOptional extends DependencyManagementRule { + private ManagedOptional(Boolean value, boolean enforcing) { + super(value, Kind.OPTIONAL, enforcing, d -> d.setOptional(value)); + } + } + + public static final class ManagedProperties extends DependencyManagementRule> { + private ManagedProperties(Map value, boolean enforcing) { + super(value, Kind.PROPERTIES, enforcing, d -> { + HashMap properties = new HashMap<>(d.getArtifact().getProperties()); + properties.putAll(value); + return d.setArtifact(d.getArtifact().setProperties(properties)); + }); + } + } + + public static final class ManagedExclusions extends DependencyManagementRule> { + private ManagedExclusions(Collection value, boolean enforcing) { + super(value, Kind.EXCLUSIONS, enforcing, d -> d.setExclusions(value)); + } + } +} diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java index 747163985..dc60ff1b4 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -38,6 +38,16 @@ * @noextend This interface is not intended to be extended by clients. */ public interface DependencyNode { + /** + * Enums for attributes being managed. + */ + enum ManagedSubject { + VERSION, SCOPE, OPTIONAL, PROPERTIES, EXCLUSIONS + } + + enum ManagementKind { + ADJUSTING, ENFORCING + } /** * A bit flag indicating the dependency version was subject to dependency management diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java new file mode 100644 index 000000000..cc2433a98 --- /dev/null +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java @@ -0,0 +1,74 @@ +/* + * 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.spi.platform; + +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.version.Version; + +import java.util.List; + +/** + * A definition of platform; it can span multiple "levels", from "what BOM offers" to (optionally) much more. + */ +public interface Platform { + /** + * Platform mode of operation. + */ + enum Mode { + /** + * In this mode platform "only" makes sure that platform constituents are processed together, "logically grouped". + */ + RELAXED, + /** + * In this mode platform aside of "logically grouping", also makes versioning strict, enforcing that versions + * do not fall outside of platform defined versions. + */ + STRICT + } + + /** + * Platform key. + */ + String getPlatformKey(); + + /** + * Platform name (for human consumption). + */ + String getPlatformName(); + + /** + * The mode this platform was set up for. + */ + Mode getPlatformMode(); + + /** + * The version of this platform. + */ + Version getPlatformVersion(); + + + /** + * The managed dependencies this platform contains. + */ + List getManagedDependencies(); + + // checksums + // relocations + // repositories +} diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java new file mode 100644 index 000000000..2ceaea12d --- /dev/null +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java @@ -0,0 +1,45 @@ +/* + * 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.spi.platform; + +import org.eclipse.aether.version.Version; + +import java.util.Collection; + +/** + * A definition of platform group; holds multiple {@link Platform} having same key but different version. + */ +public interface PlatformGroup { + /** + * The common key of this platform. + */ + String getKey(); + + /** + * The versions this group contains. + */ + Collection getVersions(); + + /** + * + * @param version + * @return + */ + Platform getPlatformForVersion(Version version); +} diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java new file mode 100644 index 000000000..09540a971 --- /dev/null +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java @@ -0,0 +1,38 @@ +/* + * 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.spi.platform; + +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.version.Version; + +import java.util.Collection; +import java.util.Optional; + +/** + * The platform manager. + */ +public interface PlatformManager { + /** + * Returns + * @param artifact + * @return + */ + Optional getPlatformForArtifact(Artifact artifact); +} diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java new file mode 100644 index 000000000..615c030dc --- /dev/null +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java @@ -0,0 +1,23 @@ +// CHECKSTYLE_OFF: RegexpHeader +/* + * 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. + */ +/** + * The contract for platform management. + */ +package org.eclipse.aether.spi.platform; From a781b7f3c8f580e49aa6253ee0c5948687fbf01f Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 2 Oct 2025 11:56:50 +0200 Subject: [PATCH 02/13] WIP --- .../collection/DependencyManagement.java | 33 ++++ .../aether/collection/DependencyManager.java | 1 - .../aether/graph/DefaultDependencyNode.java | 64 ++++++-- .../graph/DependencyManagementRule.java | 77 +++++++--- .../graph/DependencyManagementSubject.java | 32 ++++ .../eclipse/aether/graph/DependencyNode.java | 39 +++-- .../impl/collect/PremanagedDependency.java | 101 +++++++----- .../eclipse/aether/spi/platform/Platform.java | 5 +- .../aether/spi/platform/PlatformGroup.java | 4 +- .../aether/spi/platform/PlatformManager.java | 7 +- .../test/util/DependencyGraphParser.java | 9 +- .../manager/AbstractDependencyManager.java | 145 +++++++----------- .../graph/manager/DependencyManagerUtils.java | 11 +- .../manager/TransitiveDependencyManager.java | 26 ---- .../transformer/ClassicConflictResolver.java | 5 +- .../transformer/PathConflictResolver.java | 5 +- .../graph/manager/DependencyManagerTest.java | 2 + 17 files changed, 349 insertions(+), 217 deletions(-) create mode 100644 maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java 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 71bfd5102..8d6eed9e5 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 @@ -19,16 +19,21 @@ package org.eclipse.aether.collection; import java.util.Collection; +import java.util.List; import java.util.Map; +import org.eclipse.aether.graph.DependencyManagementRule; import org.eclipse.aether.graph.Exclusion; +import static java.util.Objects.requireNonNull; + /** * The management updates to apply to a dependency. * * @see DependencyManager#manageDependency(org.eclipse.aether.graph.Dependency) */ public final class DependencyManagement { + private final List> rules; private String version; @@ -42,9 +47,27 @@ public final class DependencyManagement { /** * Creates an empty management update. + * + * @deprecated */ + @Deprecated public DependencyManagement() { // enables default constructor + this.rules = null; + } + + /** + * Creates instance with given rules. + */ + public DependencyManagement(List> rules) { + this.rules = requireNonNull(rules); + } + + /** + * Returns the {@link DependencyManagementRule} or {@code null}. + */ + public List> getRules() { + return rules; } /** @@ -53,6 +76,7 @@ public DependencyManagement() { * @return The new version or {@code null} if the version is not managed and the existing dependency version should * remain unchanged. */ + @Deprecated public String getVersion() { return version; } @@ -63,6 +87,7 @@ public String getVersion() { * @param version The new version, may be {@code null} if the version is not managed. * @return This management update for chaining, never {@code null}. */ + @Deprecated public DependencyManagement setVersion(String version) { this.version = version; return this; @@ -74,6 +99,7 @@ public DependencyManagement setVersion(String version) { * @return The new scope or {@code null} if the scope is not managed and the existing dependency scope should remain * unchanged. */ + @Deprecated public String getScope() { return scope; } @@ -84,6 +110,7 @@ public String getScope() { * @param scope The new scope, may be {@code null} if the scope is not managed. * @return This management update for chaining, never {@code null}. */ + @Deprecated public DependencyManagement setScope(String scope) { this.scope = scope; return this; @@ -95,6 +122,7 @@ public DependencyManagement setScope(String scope) { * @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. */ + @Deprecated public Boolean getOptional() { return optional; } @@ -105,6 +133,7 @@ public Boolean getOptional() { * @param optional The optional flag, may be {@code null} if the flag is not managed. * @return This management update for chaining, never {@code null}. */ + @Deprecated public DependencyManagement setOptional(Boolean optional) { this.optional = optional; return this; @@ -118,6 +147,7 @@ public DependencyManagement setOptional(Boolean optional) { * @return The new exclusions or {@code null} if the exclusions are not managed and the existing dependency * exclusions should remain unchanged. */ + @Deprecated public Collection getExclusions() { return exclusions; } @@ -130,6 +160,7 @@ public Collection getExclusions() { * @param exclusions The new exclusions, may be {@code null} if the exclusions are not managed. * @return This management update for chaining, never {@code null}. */ + @Deprecated public DependencyManagement setExclusions(Collection exclusions) { this.exclusions = exclusions; return this; @@ -143,6 +174,7 @@ public DependencyManagement setExclusions(Collection exclusions) { * @return The new artifact properties or {@code null} if the properties are not managed and the existing properties * should remain unchanged. */ + @Deprecated public Map getProperties() { return properties; } @@ -155,6 +187,7 @@ public Map getProperties() { * @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}. */ + @Deprecated public DependencyManagement setProperties(Map properties) { this.properties = properties; return this; diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java index d24f79c35..9184cec63 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java @@ -33,7 +33,6 @@ * CollectRequest) */ public interface DependencyManager { - /** * Applies dependency management to the specified dependency. * diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java index 3d7c4fde0..ee9d55b19 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java @@ -51,7 +51,7 @@ public final class DefaultDependencyNode implements DependencyNode { private Version version; - private byte managedBits; + private Map managedSubjects = new HashMap<>(); private List repositories; @@ -104,7 +104,7 @@ public DefaultDependencyNode(DependencyNode node) { children = new ArrayList<>(0); setAliases(node.getAliases()); setRequestContext(node.getRequestContext()); - setManagedBits(node.getManagedBits()); + setManagedSubjects(node.getManagedSubjects()); setRelocations(node.getRelocations()); setRepositories(node.getRepositories()); setVersion(node.getVersion()); @@ -113,10 +113,12 @@ public DefaultDependencyNode(DependencyNode node) { setData(data.isEmpty() ? null : new HashMap<>(data)); } + @Override public List getChildren() { return children; } + @Override public void setChildren(List children) { if (children == null) { this.children = new ArrayList<>(0); @@ -125,14 +127,17 @@ public void setChildren(List children) { } } + @Override public Dependency getDependency() { return dependency; } + @Override public Artifact getArtifact() { return artifact; } + @Override public void setArtifact(Artifact artifact) { if (dependency == null) { throw new IllegalStateException("node does not have a dependency"); @@ -141,6 +146,7 @@ public void setArtifact(Artifact artifact) { this.artifact = dependency.getArtifact(); } + @Override public List getRelocations() { return relocations; } @@ -158,6 +164,7 @@ public void setRelocations(List relocations) { } } + @Override public Collection getAliases() { return aliases; } @@ -175,6 +182,7 @@ public void setAliases(Collection aliases) { } } + @Override public VersionConstraint getVersionConstraint() { return versionConstraint; } @@ -188,6 +196,7 @@ public void setVersionConstraint(VersionConstraint versionConstraint) { this.versionConstraint = versionConstraint; } + @Override public Version getVersion() { return version; } @@ -201,6 +210,7 @@ public void setVersion(Version version) { this.version = version; } + @Override public void setScope(String scope) { if (dependency == null) { throw new IllegalStateException("node does not have a dependency"); @@ -208,6 +218,7 @@ public void setScope(String scope) { dependency = dependency.setScope(scope); } + @Override public void setOptional(Boolean optional) { if (dependency == null) { throw new IllegalStateException("node does not have a dependency"); @@ -215,20 +226,47 @@ public void setOptional(Boolean optional) { dependency = dependency.setOptional(optional); } + @Override public int getManagedBits() { - return managedBits; + byte res = 0; + if (managedSubjects.containsKey(DependencyManagementSubject.VERSION)) { + res |= DependencyNode.MANAGED_VERSION; + } + if (managedSubjects.containsKey(DependencyManagementSubject.SCOPE)) { + res |= DependencyNode.MANAGED_SCOPE; + } + if (managedSubjects.containsKey(DependencyManagementSubject.OPTIONAL)) { + res |= DependencyNode.MANAGED_OPTIONAL; + } + if (managedSubjects.containsKey(DependencyManagementSubject.PROPERTIES)) { + res |= DependencyNode.MANAGED_PROPERTIES; + } + if (managedSubjects.containsKey(DependencyManagementSubject.EXCLUSIONS)) { + res |= DependencyNode.MANAGED_EXCLUSIONS; + } + return res; } - /** - * Sets a bit field indicating which attributes of this node were subject to dependency management. - * - * @param managedBits The bit field indicating the managed attributes or {@code 0} if dependency management wasn't - * applied. - */ + @Deprecated public void setManagedBits(int managedBits) { - this.managedBits = (byte) (managedBits & 0x1F); + throw new IllegalArgumentException("bits are not supported"); } + public void setManagedSubjects(Map managedSubjects) { + this.managedSubjects = managedSubjects; + } + + @Override + public Map getManagedSubjects() { + return managedSubjects; + } + + @Override + public boolean isManagedSubjectEnforced(DependencyManagementSubject subject) { + return managedSubjects.getOrDefault(subject, false); + } + + @Override public List getRepositories() { return repositories; } @@ -246,18 +284,22 @@ public void setRepositories(List repositories) { } } + @Override public String getRequestContext() { return context; } + @Override public void setRequestContext(String context) { this.context = (context != null) ? context.intern() : ""; } + @Override public Map getData() { return data; } + @Override public void setData(Map data) { if (data == null) { this.data = Collections.emptyMap(); @@ -266,6 +308,7 @@ public void setData(Map data) { } } + @Override public void setData(Object key, Object value) { requireNonNull(key, "key cannot be null"); @@ -285,6 +328,7 @@ public void setData(Object key, Object value) { } } + @Override public boolean accept(DependencyVisitor visitor) { if (Thread.currentThread().isInterrupted()) { throw new RuntimeException(new InterruptedException("Thread interrupted")); diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java index dfebd4fac..11a982b26 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java @@ -21,20 +21,18 @@ import java.util.Collection; import java.util.HashMap; import java.util.Map; +import java.util.Objects; import java.util.function.UnaryOperator; import static java.util.Objects.requireNonNull; /** - * Represents a dependency management rule, a managed value of given attribute. + * Represents a dependency management rule, a managed value of given {@link DependencyManagementSubject}. * + * @param the type of subject rule operates on. * @since 2.0.13 */ public class DependencyManagementRule implements UnaryOperator { - public enum Kind { - VERSION, SCOPE, OPTIONAL, PROPERTIES, EXCLUSIONS - } - public static ManagedVersion managedVersion(String version, boolean enforcing) { return new ManagedVersion(version, enforcing); } @@ -47,8 +45,12 @@ public static ManagedOptional managedOptional(Boolean optional, boolean enforcin return new ManagedOptional(optional, enforcing); } - public static ManagedProperties managedProperties(Map properties, boolean enforcing) { - return new ManagedProperties(properties, enforcing); + public static ManagedPropertiesPut managedPropertiesPut(Map properties, boolean enforcing) { + return new ManagedPropertiesPut(properties, enforcing); + } + + public static ManagedPropertiesRemove managedPropertiesRemove(Collection keys, boolean enforcing) { + return new ManagedPropertiesRemove(keys, enforcing); } public static ManagedExclusions managedExclusions(Collection exclusions, boolean enforcing) { @@ -57,25 +59,30 @@ public static ManagedExclusions managedExclusions(Collection exclusio private final T value; - private final Kind kind; + private final DependencyManagementSubject subject; private final boolean enforcing; private final UnaryOperator operator; - protected DependencyManagementRule(T value, Kind kind, boolean enforcing, UnaryOperator operator) { + private final int hashCode; + + protected DependencyManagementRule( + T value, DependencyManagementSubject subject, boolean enforcing, UnaryOperator operator) { this.value = requireNonNull(value); - this.kind = requireNonNull(kind); + this.subject = requireNonNull(subject); this.enforcing = enforcing; this.operator = requireNonNull(operator); + + this.hashCode = Objects.hash(value, subject, enforcing); } public T getValue() { return value; } - public Kind getKind() { - return kind; + public DependencyManagementSubject getSubject() { + return subject; } public boolean isEnforcing() { @@ -88,37 +95,67 @@ public Dependency apply(Dependency dependency) { return operator.apply(dependency); } + @Override + public boolean equals(Object o) { + if (!(o instanceof DependencyManagementRule)) { + return false; + } + DependencyManagementRule that = (DependencyManagementRule) o; + return enforcing == that.enforcing && Objects.equals(value, that.value) && subject == that.subject; + } + + @Override + public int hashCode() { + return hashCode; + } + public static final class ManagedVersion extends DependencyManagementRule { private ManagedVersion(String value, boolean enforcing) { - super(value, Kind.VERSION, enforcing, d -> d.setArtifact(d.getArtifact().setVersion(value))); + super( + value, + DependencyManagementSubject.VERSION, + enforcing, + d -> d.setArtifact(d.getArtifact().setVersion(value))); } } public static final class ManagedScope extends DependencyManagementRule { private ManagedScope(String value, boolean enforcing) { - super(value, Kind.SCOPE, enforcing, d -> d.setScope(value)); + super(value, DependencyManagementSubject.SCOPE, enforcing, d -> d.setScope(value)); } } public static final class ManagedOptional extends DependencyManagementRule { private ManagedOptional(Boolean value, boolean enforcing) { - super(value, Kind.OPTIONAL, enforcing, d -> d.setOptional(value)); + super(value, DependencyManagementSubject.OPTIONAL, enforcing, d -> d.setOptional(value)); } } - public static final class ManagedProperties extends DependencyManagementRule> { - private ManagedProperties(Map value, boolean enforcing) { - super(value, Kind.PROPERTIES, enforcing, d -> { - HashMap properties = new HashMap<>(d.getArtifact().getProperties()); + public static final class ManagedPropertiesPut extends DependencyManagementRule> { + private ManagedPropertiesPut(Map value, boolean enforcing) { + super(value, DependencyManagementSubject.PROPERTIES, enforcing, d -> { + HashMap properties = + new HashMap<>(d.getArtifact().getProperties()); properties.putAll(value); return d.setArtifact(d.getArtifact().setProperties(properties)); }); } } + public static final class ManagedPropertiesRemove extends DependencyManagementRule> { + private ManagedPropertiesRemove(Collection value, boolean enforcing) { + super(value, DependencyManagementSubject.PROPERTIES, enforcing, d -> { + HashMap properties = + new HashMap<>(d.getArtifact().getProperties()); + value.forEach(properties::remove); + return d.setArtifact(d.getArtifact().setProperties(properties)); + }); + } + } + public static final class ManagedExclusions extends DependencyManagementRule> { private ManagedExclusions(Collection value, boolean enforcing) { - super(value, Kind.EXCLUSIONS, enforcing, d -> d.setExclusions(value)); + super(value, DependencyManagementSubject.EXCLUSIONS, enforcing, d -> d.setExclusions(value)); } } } diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java new file mode 100644 index 000000000..1f0645e7d --- /dev/null +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java @@ -0,0 +1,32 @@ +/* + * 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.graph; + +/** + * Represents a dependency management subject, a managed attribute of dependency. + * + * @since 2.0.13 + */ +public enum DependencyManagementSubject { + VERSION, + SCOPE, + OPTIONAL, + PROPERTIES, + EXCLUSIONS +} diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java index dc60ff1b4..5b37d8fe1 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -38,50 +38,49 @@ * @noextend This interface is not intended to be extended by clients. */ public interface DependencyNode { - /** - * Enums for attributes being managed. - */ - enum ManagedSubject { - VERSION, SCOPE, OPTIONAL, PROPERTIES, EXCLUSIONS - } - - enum ManagementKind { - ADJUSTING, ENFORCING - } - /** * A bit flag indicating the dependency version was subject to dependency management * * @see #getManagedBits() + * @deprecated */ + @Deprecated int MANAGED_VERSION = 0x01; /** * A bit flag indicating the dependency scope was subject to dependency management * * @see #getManagedBits() + * @deprecated */ + @Deprecated int MANAGED_SCOPE = 0x02; /** * A bit flag indicating the optional flag was subject to dependency management * * @see #getManagedBits() + * @deprecated */ + @Deprecated int MANAGED_OPTIONAL = 0x04; /** * A bit flag indicating the artifact properties were subject to dependency management * * @see #getManagedBits() + * @deprecated */ + @Deprecated int MANAGED_PROPERTIES = 0x08; /** * A bit flag indicating the exclusions were subject to dependency management * * @see #getManagedBits() + * @deprecated */ + @Deprecated int MANAGED_EXCLUSIONS = 0x10; /** @@ -180,9 +179,27 @@ enum ManagementKind { * @return A bit field containing any of the bits {@link #MANAGED_VERSION}, {@link #MANAGED_SCOPE}, * {@link #MANAGED_OPTIONAL}, {@link #MANAGED_PROPERTIES} and {@link #MANAGED_EXCLUSIONS} if the * corresponding attribute was set via dependency management. + * @deprecated */ + @Deprecated int getManagedBits(); + /** + * Returns what kind of management was applied to this node. + * + * @since 2.0.13 + */ + Map getManagedSubjects(); + + /** + * Returns {@code true} if given subject is managed with {@link DependencyManagementRule#isEnforcing()} on this node. + * That is, this method is + * + * @see DependencyManagementRule#isEnforcing() + * @since 2.0.13 + */ + boolean isManagedSubjectEnforced(DependencyManagementSubject subject); + /** * Gets the remote repositories from which this node's artifact shall be resolved. * diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java index c0a6ef3bb..c5766759d 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java @@ -29,7 +29,8 @@ import org.eclipse.aether.collection.DependencyManager; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.graph.DependencyManagementRule; +import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.Exclusion; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; @@ -54,7 +55,10 @@ public class PremanagedDependency { */ final Map premanagedProperties; - final int managedBits; + /** + * @since 2.0.13 + */ + final Map managedSubjects; final Dependency managedDependency; @@ -67,7 +71,7 @@ public class PremanagedDependency { Boolean premanagedOptional, Collection premanagedExclusions, Map premanagedProperties, - int managedBits, + Map managedSubjects, Dependency managedDependency, boolean premanagedState) { this.premanagedVersion = premanagedVersion; @@ -80,7 +84,7 @@ public class PremanagedDependency { this.premanagedProperties = premanagedProperties != null ? Collections.unmodifiableMap(new HashMap<>(premanagedProperties)) : null; - this.managedBits = managedBits; + this.managedSubjects = managedSubjects; this.managedDependency = managedDependency; this.premanagedState = premanagedState; } @@ -90,51 +94,78 @@ public static PremanagedDependency create( Dependency dependency, boolean disableVersionManagement, boolean premanagedState) { - DependencyManagement depMngt = depManager != null ? depManager.manageDependency(dependency) : null; + DependencyManagement management = depManager != null ? depManager.manageDependency(dependency) : null; - int managedBits = 0; + Map managedSubjects = new HashMap<>(); String premanagedVersion = null; String premanagedScope = null; Boolean premanagedOptional = null; Collection premanagedExclusions = null; Map premanagedProperties = null; - if (depMngt != null) { - if (depMngt.getVersion() != null && !disableVersionManagement) { - Artifact artifact = dependency.getArtifact(); - premanagedVersion = artifact.getVersion(); - dependency = dependency.setArtifact(artifact.setVersion(depMngt.getVersion())); - managedBits |= DependencyNode.MANAGED_VERSION; - } - if (depMngt.getProperties() != null) { - Artifact artifact = dependency.getArtifact(); - premanagedProperties = artifact.getProperties(); - dependency = dependency.setArtifact(artifact.setProperties(depMngt.getProperties())); - managedBits |= DependencyNode.MANAGED_PROPERTIES; - } - if (depMngt.getScope() != null) { - premanagedScope = dependency.getScope(); - dependency = dependency.setScope(depMngt.getScope()); - managedBits |= DependencyNode.MANAGED_SCOPE; - } - if (depMngt.getOptional() != null) { - premanagedOptional = dependency.isOptional(); - dependency = dependency.setOptional(depMngt.getOptional()); - managedBits |= DependencyNode.MANAGED_OPTIONAL; - } - if (depMngt.getExclusions() != null) { - premanagedExclusions = dependency.getExclusions(); - dependency = dependency.setExclusions(depMngt.getExclusions()); - managedBits |= DependencyNode.MANAGED_EXCLUSIONS; + if (management != null) { + if (management.getRules() != null) { + for (DependencyManagementRule rule : management.getRules()) { + DependencyManagementSubject subject = rule.getSubject(); + if (subject == DependencyManagementSubject.VERSION) { + if (disableVersionManagement) { + continue; + } + premanagedVersion = dependency.getArtifact().getVersion(); + } else if (subject == DependencyManagementSubject.SCOPE) { + premanagedScope = dependency.getScope(); + } else if (subject == DependencyManagementSubject.OPTIONAL) { + premanagedOptional = dependency.isOptional(); + } else if (subject == DependencyManagementSubject.PROPERTIES) { + premanagedProperties = dependency.getArtifact().getProperties(); + } else if (subject == DependencyManagementSubject.EXCLUSIONS) { + premanagedExclusions = dependency.getExclusions(); + } else { + throw new IllegalArgumentException("unknown subject " + subject); + } + dependency = rule.apply(dependency); + managedSubjects.put(subject, rule.isEnforcing()); + } + } else { + // legacy path: here there are no means to distinguish "management" as enforced or advised (so all are + // enforced) + if (management.getVersion() != null && !disableVersionManagement) { + Artifact artifact = dependency.getArtifact(); + premanagedVersion = artifact.getVersion(); + dependency = dependency.setArtifact(artifact.setVersion(management.getVersion())); + managedSubjects.put(DependencyManagementSubject.VERSION, true); + } + if (management.getProperties() != null) { + Artifact artifact = dependency.getArtifact(); + premanagedProperties = artifact.getProperties(); + dependency = dependency.setArtifact(artifact.setProperties(management.getProperties())); + managedSubjects.put(DependencyManagementSubject.PROPERTIES, true); + } + if (management.getScope() != null) { + premanagedScope = dependency.getScope(); + dependency = dependency.setScope(management.getScope()); + managedSubjects.put(DependencyManagementSubject.SCOPE, true); + } + if (management.getOptional() != null) { + premanagedOptional = dependency.isOptional(); + dependency = dependency.setOptional(management.getOptional()); + managedSubjects.put(DependencyManagementSubject.OPTIONAL, true); + } + if (management.getExclusions() != null) { + premanagedExclusions = dependency.getExclusions(); + dependency = dependency.setExclusions(management.getExclusions()); + managedSubjects.put(DependencyManagementSubject.EXCLUSIONS, true); + } } } + return new PremanagedDependency( premanagedVersion, premanagedScope, premanagedOptional, premanagedExclusions, premanagedProperties, - managedBits, + managedSubjects, dependency, premanagedState); } @@ -144,7 +175,7 @@ public Dependency getManagedDependency() { } public void applyTo(DefaultDependencyNode child) { - child.setManagedBits(managedBits); + child.setManagedSubjects(managedSubjects); if (premanagedState) { child.setData(DependencyManagerUtils.NODE_DATA_PREMANAGED_VERSION, premanagedVersion); child.setData(DependencyManagerUtils.NODE_DATA_PREMANAGED_SCOPE, premanagedScope); diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java index cc2433a98..b3ec370cf 100644 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java @@ -18,11 +18,11 @@ */ package org.eclipse.aether.spi.platform; +import java.util.List; + import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.version.Version; -import java.util.List; - /** * A definition of platform; it can span multiple "levels", from "what BOM offers" to (optionally) much more. */ @@ -62,7 +62,6 @@ enum Mode { */ Version getPlatformVersion(); - /** * The managed dependencies this platform contains. */ diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java index 2ceaea12d..0cbf635aa 100644 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java @@ -18,10 +18,10 @@ */ package org.eclipse.aether.spi.platform; -import org.eclipse.aether.version.Version; - import java.util.Collection; +import org.eclipse.aether.version.Version; + /** * A definition of platform group; holds multiple {@link Platform} having same key but different version. */ diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java index 09540a971..45645ddd9 100644 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java +++ b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java @@ -18,13 +18,10 @@ */ package org.eclipse.aether.spi.platform; -import org.eclipse.aether.artifact.Artifact; -import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.version.Version; - -import java.util.Collection; import java.util.Optional; +import org.eclipse.aether.artifact.Artifact; + /** * The platform manager. */ diff --git a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java index 18da45bb7..25216912a 100644 --- a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java +++ b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java @@ -38,6 +38,7 @@ import org.eclipse.aether.artifact.DefaultArtifact; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.version.InvalidVersionSpecificationException; import org.eclipse.aether.version.VersionScheme; @@ -291,16 +292,16 @@ private DependencyNode build(DependencyNode parent, LineContext ctx, boolean isR DefaultArtifact artifact = new DefaultArtifact(def.coords, def.properties); Dependency dependency = new Dependency(artifact, def.scope, def.optional); node = new DefaultDependencyNode(dependency); - int managedBits = 0; + Map managedSubjects = new HashMap<>(); if (def.premanagedScope != null) { - managedBits |= DependencyNode.MANAGED_SCOPE; + managedSubjects.put(DependencyManagementSubject.SCOPE, true); node.setData("premanaged.scope", def.premanagedScope); } if (def.premanagedVersion != null) { - managedBits |= DependencyNode.MANAGED_VERSION; + managedSubjects.put(DependencyManagementSubject.VERSION, true); node.setData("premanaged.version", def.premanagedVersion); } - node.setManagedBits(managedBits); + node.setManagedSubjects(managedSubjects); if (def.relocations != null) { List relocations = new ArrayList<>(); for (String relocation : def.relocations) { 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 556b9c588..99dc5c147 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 @@ -20,15 +20,18 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; 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.DependencyManagementRule; import org.eclipse.aether.graph.Exclusion; import org.eclipse.aether.scope.ScopeManager; import org.eclipse.aether.scope.SystemDependencyScope; @@ -206,14 +209,14 @@ private boolean containsManagedVersion(Key key) { return managedVersions != null && managedVersions.containsKey(key); } - private String getManagedVersion(Key key) { + private AbstractDependencyManager getManagedVersion(Key key) { for (AbstractDependencyManager ancestor : path) { if (ancestor.managedVersions != null && ancestor.managedVersions.containsKey(key)) { - return ancestor.managedVersions.get(key); + return ancestor; } } if (depth == 1 && managedVersions != null && managedVersions.containsKey(key)) { - return managedVersions.get(key); + return this; } return null; } @@ -227,14 +230,14 @@ private boolean containsManagedScope(Key key) { return managedScopes != null && managedScopes.containsKey(key); } - private String getManagedScope(Key key) { + private AbstractDependencyManager getManagedScope(Key key) { for (AbstractDependencyManager ancestor : path) { if (ancestor.managedScopes != null && ancestor.managedScopes.containsKey(key)) { - return ancestor.managedScopes.get(key); + return ancestor; } } if (depth == 1 && managedScopes != null && managedScopes.containsKey(key)) { - return managedScopes.get(key); + return this; } return null; } @@ -248,14 +251,14 @@ private boolean containsManagedOptional(Key key) { return managedOptionals != null && managedOptionals.containsKey(key); } - private Boolean getManagedOptional(Key key) { + private AbstractDependencyManager getManagedOptional(Key key) { for (AbstractDependencyManager ancestor : path) { if (ancestor.managedOptionals != null && ancestor.managedOptionals.containsKey(key)) { - return ancestor.managedOptionals.get(key); + return ancestor; } } if (depth == 1 && managedOptionals != null && managedOptionals.containsKey(key)) { - return managedOptionals.get(key); + return this; } return null; } @@ -276,14 +279,14 @@ private boolean containsManagedLocalPath(Key key) { * @param key the dependency key * @return the managed local path, or null if not managed */ - private String getManagedLocalPath(Key key) { + private AbstractDependencyManager getManagedLocalPath(Key key) { for (AbstractDependencyManager ancestor : path) { if (ancestor.managedLocalPaths != null && ancestor.managedLocalPaths.containsKey(key)) { - return ancestor.managedLocalPaths.get(key); + return ancestor; } } if (managedLocalPaths != null && managedLocalPaths.containsKey(key)) { - return managedLocalPaths.get(key); + return this; } return null; } @@ -334,22 +337,20 @@ public DependencyManager deriveChildManager(DependencyCollectionContext context) managedVersions.put(key, version); } - if (isInheritedDerived()) { - String scope = managedDependency.getScope(); - if (!scope.isEmpty() && !containsManagedScope(key)) { - if (managedScopes == null) { - managedScopes = MMap.emptyNotDone(); - } - managedScopes.put(key, scope); + String scope = managedDependency.getScope(); + if (!scope.isEmpty() && !containsManagedScope(key)) { + if (managedScopes == null) { + managedScopes = MMap.emptyNotDone(); } + managedScopes.put(key, scope); + } - Boolean optional = managedDependency.getOptional(); - if (optional != null && !containsManagedOptional(key)) { - if (managedOptionals == null) { - managedOptionals = MMap.emptyNotDone(); - } - managedOptionals.put(key, optional); + Boolean optional = managedDependency.getOptional(); + if (optional != null && !containsManagedOptional(key)) { + if (managedOptionals == null) { + managedOptionals = MMap.emptyNotDone(); } + managedOptionals.put(key, optional); } String localPath = systemDependencyScope == null @@ -390,62 +391,52 @@ public DependencyManager deriveChildManager(DependencyCollectionContext context) @Override public DependencyManagement manageDependency(Dependency dependency) { requireNonNull(dependency, "dependency cannot be null"); - DependencyManagement management = null; + ArrayList> rules = new ArrayList<>(); Key key = new Key(dependency.getArtifact()); if (isApplied()) { - String version = getManagedVersion(key); + AbstractDependencyManager versionOwner = getManagedVersion(key); // is managed locally by model builder // apply only rules coming from "higher" levels - if (version != null) { - management = new DependencyManagement(); - management.setVersion(version); + if (versionOwner != null) { + rules.add(DependencyManagementRule.managedVersion( + versionOwner.managedVersions.get(key), versionOwner.path.isEmpty())); } - String scope = getManagedScope(key); + AbstractDependencyManager scopeOwner = getManagedScope(key); // is managed locally by model builder // apply only rules coming from "higher" levels - if (scope != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setScope(scope); + if (scopeOwner != null) { + String managedScope = scopeOwner.managedScopes.get(key); + rules.add(DependencyManagementRule.managedScope(managedScope, scopeOwner.path.isEmpty())); if (systemDependencyScope != null - && !systemDependencyScope.is(scope) + && !systemDependencyScope.is(managedScope) && systemDependencyScope.getSystemPath(dependency.getArtifact()) != null) { - HashMap properties = - new HashMap<>(dependency.getArtifact().getProperties()); - systemDependencyScope.setSystemPath(properties, null); - management.setProperties(properties); + rules.add(DependencyManagementRule.managedPropertiesRemove( + Collections.singleton(ArtifactProperties.LOCAL_PATH), false)); } } // system scope paths always applied to have them aligned // (same artifact == same path) in whole graph if (systemDependencyScope != null - && (scope != null && systemDependencyScope.is(scope) - || (scope == null && systemDependencyScope.is(dependency.getScope())))) { - String localPath = getManagedLocalPath(key); - if (localPath != null) { - if (management == null) { - management = new DependencyManagement(); - } - HashMap properties = - new HashMap<>(dependency.getArtifact().getProperties()); - systemDependencyScope.setSystemPath(properties, localPath); - management.setProperties(properties); + && (scopeOwner != null && systemDependencyScope.is(scopeOwner.managedScopes.get(key)) + || (scopeOwner == null && systemDependencyScope.is(dependency.getScope())))) { + AbstractDependencyManager localPathOwner = getManagedLocalPath(key); + if (localPathOwner != null) { + HashMap properties = new HashMap<>(); + properties.put(ArtifactProperties.LOCAL_PATH, localPathOwner.managedLocalPaths.get(key)); + rules.add(DependencyManagementRule.managedPropertiesPut(properties, false)); } } // optional is not managed by model builder // apply only rules coming from "higher" levels - Boolean optional = getManagedOptional(key); - if (optional != null) { - if (management == null) { - management = new DependencyManagement(); - } - management.setOptional(optional); + AbstractDependencyManager optionalOwner = getManagedOptional(key); + if (optionalOwner != null) { + rules.add(DependencyManagementRule.managedOptional( + optionalOwner.managedOptionals.get(key), optionalOwner.path.isEmpty())); } } @@ -456,15 +447,15 @@ public DependencyManagement manageDependency(Dependency dependency) { // so we merge it here even from same level Collection exclusions = getManagedExclusions(key); if (exclusions != null) { - if (management == null) { - management = new DependencyManagement(); - } Collection result = new LinkedHashSet<>(dependency.getExclusions()); result.addAll(exclusions); - management.setExclusions(result); + rules.add(DependencyManagementRule.managedExclusions(result, false)); } - return management; + if (rules.isEmpty()) { + return null; + } + return new DependencyManagement(rules); } /** @@ -474,34 +465,6 @@ protected boolean isDerived() { return depth < deriveUntil; } - /** - * Manages dependency properties including "version", "scope", "optional", "local path", and "exclusions". - *

- * Property management behavior: - *

    - *
  • Version: Follows {@link #isDerived()} pattern. Management is applied only at higher - * levels to avoid interference with the model builder.
  • - *
  • Scope: Derived from root only due to inheritance in dependency graphs. Special handling - * for "system" scope to align artifact paths.
  • - *
  • Optional: Derived from root only due to inheritance in dependency graphs.
  • - *
  • Local path: Managed only when scope is or was set to "system" to ensure consistent - * artifact path alignment.
  • - *
  • Exclusions: Accumulated additively from root to current level throughout the entire - * dependency path.
  • - *
- *

- * Inheritance handling: Since "scope" and "optional" properties inherit through dependency - * graphs (beyond model builder scope), they are derived only from the root node. The actual manager - * implementation determines specific handling behavior. - *

- * Default behavior: Defaults to {@link #isDerived()} to maintain compatibility with - * "classic" behavior (equivalent to {@code deriveUntil=2}). For custom transitivity management, override - * this method or ensure inherited managed properties are handled during graph transformation. - */ - protected boolean isInheritedDerived() { - return isDerived(); - } - /** * Returns {@code true} if current dependency should be managed according to so far collected/derived rules. */ 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 e83fd0669..83dd519c6 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 @@ -23,6 +23,7 @@ import org.eclipse.aether.ConfigurationProperties; import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.graph.Exclusion; @@ -87,7 +88,7 @@ public final class DependencyManagerUtils { * or if {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static String getPremanagedVersion(DependencyNode node) { - if ((node.getManagedBits() & DependencyNode.MANAGED_VERSION) == 0) { + if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.VERSION)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_VERSION), String.class); @@ -101,7 +102,7 @@ public static String getPremanagedVersion(DependencyNode node) { * if {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static String getPremanagedScope(DependencyNode node) { - if ((node.getManagedBits() & DependencyNode.MANAGED_SCOPE) == 0) { + if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.SCOPE)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_SCOPE), String.class); @@ -115,7 +116,7 @@ public static String getPremanagedScope(DependencyNode node) { * {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static Boolean getPremanagedOptional(DependencyNode node) { - if ((node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) == 0) { + if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.OPTIONAL)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_OPTIONAL), Boolean.class); @@ -131,7 +132,7 @@ public static Boolean getPremanagedOptional(DependencyNode node) { */ @SuppressWarnings("unchecked") public static Collection getPremanagedExclusions(DependencyNode node) { - if ((node.getManagedBits() & DependencyNode.MANAGED_EXCLUSIONS) == 0) { + if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.EXCLUSIONS)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_EXCLUSIONS), Collection.class); @@ -147,7 +148,7 @@ public static Collection getPremanagedExclusions(DependencyNode node) */ @SuppressWarnings("unchecked") public static Map getPremanagedProperties(DependencyNode node) { - if ((node.getManagedBits() & DependencyNode.MANAGED_PROPERTIES) == 0) { + if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.PROPERTIES)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_PROPERTIES), Map.class); 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 b46211be0..460a52c01 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 @@ -145,30 +145,4 @@ protected DependencyManager newInstance( managedExclusions, systemDependencyScope); } - - /** - * Controls inheritance-based property derivation for scope and optional properties. - *

- * Why scope and optional are special: In dependency graphs, these two properties - * are subject to inheritance during graph transformation (which is outside ModelBuilder's scope). - * Therefore, scope and optional are derived only from the root to prevent interference with - * inheritance logic. - *

- *

- * The inheritance problem: If we managed scope/optional from sources below the root, - * we would mark nodes as "managed" in the dependency graph. The "managed" flag means "do not touch it, - * it is as it should be", which would prevent proper inheritance application during later graph - * transformation, causing nodes to end up with incorrect scope or optional states. - *

- *

- * Special case: The "system" scope has special handling due to its unique path requirements. - *

- * - * @return true only at depth 0 (root level) to ensure inheritance-based properties are only - * derived from the root, false otherwise - */ - @Override - protected boolean isInheritedDerived() { - return depth == 0; - } } diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java index 4ecd53b2e..5591af566 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java @@ -35,6 +35,7 @@ import org.eclipse.aether.collection.DependencyGraphTransformationContext; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.util.artifact.ArtifactIdUtils; @@ -675,7 +676,7 @@ private DependencyNode parent() { } private String deriveScope(DependencyNode node, String conflictId) throws RepositoryException { - if ((node.getManagedBits() & DependencyNode.MANAGED_SCOPE) != 0 + if (node.isManagedSubjectEnforced(DependencyManagementSubject.SCOPE) || (conflictId != null && resolvedIds.containsKey(conflictId))) { return scope(node.getDependency()); } @@ -702,7 +703,7 @@ private boolean deriveOptional(DependencyNode node, String conflictId) { Dependency dep = node.getDependency(); boolean optional = (dep != null) && dep.isOptional(); if (optional - || (node.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) != 0 + || node.isManagedSubjectEnforced(DependencyManagementSubject.OPTIONAL) || (conflictId != null && resolvedIds.containsKey(conflictId))) { return optional; } diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java index 985106a0b..a822c9359 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java @@ -34,6 +34,7 @@ import org.eclipse.aether.collection.DependencyGraphTransformationContext; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.util.ConfigUtils; import org.eclipse.aether.util.artifact.ArtifactIdUtils; @@ -423,12 +424,12 @@ private void pull(int levels) { private void derive(int levels, boolean winner) throws RepositoryException { if (!winner) { if (this.parent != null) { - if ((dn.getManagedBits() & DependencyNode.MANAGED_SCOPE) == 0) { + if (!dn.isManagedSubjectEnforced(DependencyManagementSubject.SCOPE)) { ScopeContext context = new ScopeContext(this.parent.scope, this.scope); state.scopeDeriver.deriveScope(context); this.scope = context.derivedScope; } - if ((dn.getManagedBits() & DependencyNode.MANAGED_OPTIONAL) == 0) { + if (!dn.isManagedSubjectEnforced(DependencyManagementSubject.OPTIONAL)) { if (!this.optional && this.parent.optional) { this.optional = true; } 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 index b32b7907e..412bdab3b 100644 --- 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 @@ -31,6 +31,7 @@ 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.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -38,6 +39,7 @@ /** * UT for {@link DependencyManager} implementations. */ +@Disabled("This is not anymore how dependency manager works") public class DependencyManagerTest { private final Artifact A1 = new DefaultArtifact("test", "a", "", "1"); From 66f73f99e72097d98bd9684cfd23865b8603ff71 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 2 Oct 2025 12:23:42 +0200 Subject: [PATCH 03/13] Drop unused for now --- .../aether/collection/DependencyManager.java | 1 + .../eclipse/aether/spi/platform/Platform.java | 73 ------------------- .../aether/spi/platform/PlatformGroup.java | 45 ------------ .../aether/spi/platform/PlatformManager.java | 35 --------- .../aether/spi/platform/package-info.java | 23 ------ 5 files changed, 1 insertion(+), 176 deletions(-) delete mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java delete mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java delete mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java delete mode 100644 maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java index 9184cec63..d24f79c35 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/collection/DependencyManager.java @@ -33,6 +33,7 @@ * CollectRequest) */ public interface DependencyManager { + /** * Applies dependency management to the specified dependency. * diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java deleted file mode 100644 index b3ec370cf..000000000 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/Platform.java +++ /dev/null @@ -1,73 +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.spi.platform; - -import java.util.List; - -import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.version.Version; - -/** - * A definition of platform; it can span multiple "levels", from "what BOM offers" to (optionally) much more. - */ -public interface Platform { - /** - * Platform mode of operation. - */ - enum Mode { - /** - * In this mode platform "only" makes sure that platform constituents are processed together, "logically grouped". - */ - RELAXED, - /** - * In this mode platform aside of "logically grouping", also makes versioning strict, enforcing that versions - * do not fall outside of platform defined versions. - */ - STRICT - } - - /** - * Platform key. - */ - String getPlatformKey(); - - /** - * Platform name (for human consumption). - */ - String getPlatformName(); - - /** - * The mode this platform was set up for. - */ - Mode getPlatformMode(); - - /** - * The version of this platform. - */ - Version getPlatformVersion(); - - /** - * The managed dependencies this platform contains. - */ - List getManagedDependencies(); - - // checksums - // relocations - // repositories -} diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java deleted file mode 100644 index 0cbf635aa..000000000 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformGroup.java +++ /dev/null @@ -1,45 +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.spi.platform; - -import java.util.Collection; - -import org.eclipse.aether.version.Version; - -/** - * A definition of platform group; holds multiple {@link Platform} having same key but different version. - */ -public interface PlatformGroup { - /** - * The common key of this platform. - */ - String getKey(); - - /** - * The versions this group contains. - */ - Collection getVersions(); - - /** - * - * @param version - * @return - */ - Platform getPlatformForVersion(Version version); -} diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java deleted file mode 100644 index 45645ddd9..000000000 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/PlatformManager.java +++ /dev/null @@ -1,35 +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.spi.platform; - -import java.util.Optional; - -import org.eclipse.aether.artifact.Artifact; - -/** - * The platform manager. - */ -public interface PlatformManager { - /** - * Returns - * @param artifact - * @return - */ - Optional getPlatformForArtifact(Artifact artifact); -} diff --git a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java b/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java deleted file mode 100644 index 615c030dc..000000000 --- a/maven-resolver-spi/src/main/java/org/eclipse/aether/spi/platform/package-info.java +++ /dev/null @@ -1,23 +0,0 @@ -// CHECKSTYLE_OFF: RegexpHeader -/* - * 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. - */ -/** - * The contract for platform management. - */ -package org.eclipse.aether.spi.platform; From 5d22788e987aaa6aa51b3e1e37734657b645ee6a Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 2 Oct 2025 12:28:19 +0200 Subject: [PATCH 04/13] Guard better for nulls --- .../aether/graph/DefaultDependencyNode.java | 23 +++++++++++++------ .../eclipse/aether/graph/DependencyNode.java | 9 +++++++- .../graph/manager/DependencyManagerUtils.java | 10 ++++---- 3 files changed, 29 insertions(+), 13 deletions(-) diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java index ee9d55b19..545ed2c1c 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java @@ -51,7 +51,7 @@ public final class DefaultDependencyNode implements DependencyNode { private Version version; - private Map managedSubjects = new HashMap<>(); + private Map managedSubjects = Collections.emptyMap(); private List repositories; @@ -229,19 +229,19 @@ public void setOptional(Boolean optional) { @Override public int getManagedBits() { byte res = 0; - if (managedSubjects.containsKey(DependencyManagementSubject.VERSION)) { + if (isManagedSubject(DependencyManagementSubject.VERSION)) { res |= DependencyNode.MANAGED_VERSION; } - if (managedSubjects.containsKey(DependencyManagementSubject.SCOPE)) { + if (isManagedSubject(DependencyManagementSubject.SCOPE)) { res |= DependencyNode.MANAGED_SCOPE; } - if (managedSubjects.containsKey(DependencyManagementSubject.OPTIONAL)) { + if (isManagedSubject(DependencyManagementSubject.OPTIONAL)) { res |= DependencyNode.MANAGED_OPTIONAL; } - if (managedSubjects.containsKey(DependencyManagementSubject.PROPERTIES)) { + if (isManagedSubject(DependencyManagementSubject.PROPERTIES)) { res |= DependencyNode.MANAGED_PROPERTIES; } - if (managedSubjects.containsKey(DependencyManagementSubject.EXCLUSIONS)) { + if (isManagedSubject(DependencyManagementSubject.EXCLUSIONS)) { res |= DependencyNode.MANAGED_EXCLUSIONS; } return res; @@ -253,7 +253,11 @@ public void setManagedBits(int managedBits) { } public void setManagedSubjects(Map managedSubjects) { - this.managedSubjects = managedSubjects; + if (managedSubjects == null) { + this.managedSubjects = Collections.emptyMap(); + } else { + this.managedSubjects = managedSubjects; + } } @Override @@ -261,6 +265,11 @@ public Map getManagedSubjects() { return managedSubjects; } + @Override + public boolean isManagedSubject(DependencyManagementSubject subject) { + return managedSubjects.containsKey(subject); + } + @Override public boolean isManagedSubjectEnforced(DependencyManagementSubject subject) { return managedSubjects.getOrDefault(subject, false); diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java index 5b37d8fe1..384e5f7af 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -191,9 +191,16 @@ public interface DependencyNode { */ Map getManagedSubjects(); + /** + * Returns {@code true} if given subject is managed. + * + * @see DependencyManagementRule#isEnforcing() + * @since 2.0.13 + */ + boolean isManagedSubject(DependencyManagementSubject subject); + /** * Returns {@code true} if given subject is managed with {@link DependencyManagementRule#isEnforcing()} on this node. - * That is, this method is * * @see DependencyManagementRule#isEnforcing() * @since 2.0.13 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 83dd519c6..ca87113ab 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 @@ -88,7 +88,7 @@ public final class DependencyManagerUtils { * or if {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static String getPremanagedVersion(DependencyNode node) { - if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.VERSION)) { + if (!node.isManagedSubject(DependencyManagementSubject.VERSION)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_VERSION), String.class); @@ -102,7 +102,7 @@ public static String getPremanagedVersion(DependencyNode node) { * if {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static String getPremanagedScope(DependencyNode node) { - if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.SCOPE)) { + if (!node.isManagedSubject(DependencyManagementSubject.SCOPE)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_SCOPE), String.class); @@ -116,7 +116,7 @@ public static String getPremanagedScope(DependencyNode node) { * {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static Boolean getPremanagedOptional(DependencyNode node) { - if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.OPTIONAL)) { + if (!node.isManagedSubject(DependencyManagementSubject.OPTIONAL)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_OPTIONAL), Boolean.class); @@ -132,7 +132,7 @@ public static Boolean getPremanagedOptional(DependencyNode node) { */ @SuppressWarnings("unchecked") public static Collection getPremanagedExclusions(DependencyNode node) { - if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.EXCLUSIONS)) { + if (!node.isManagedSubject(DependencyManagementSubject.EXCLUSIONS)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_EXCLUSIONS), Collection.class); @@ -148,7 +148,7 @@ public static Collection getPremanagedExclusions(DependencyNode node) */ @SuppressWarnings("unchecked") public static Map getPremanagedProperties(DependencyNode node) { - if (!node.getManagedSubjects().containsKey(DependencyManagementSubject.PROPERTIES)) { + if (!node.isManagedSubject(DependencyManagementSubject.PROPERTIES)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_PROPERTIES), Map.class); From 2ddd3dbb4bf6d451498b74164786271950ac9593 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 2 Oct 2025 12:37:16 +0200 Subject: [PATCH 05/13] Javadoc --- .../util/graph/manager/AbstractDependencyManager.java | 6 ++++-- 1 file changed, 4 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 99dc5c147..508b5096e 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 @@ -32,6 +32,7 @@ import org.eclipse.aether.collection.DependencyManager; import org.eclipse.aether.graph.Dependency; import org.eclipse.aether.graph.DependencyManagementRule; +import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.Exclusion; import org.eclipse.aether.scope.ScopeManager; import org.eclipse.aether.scope.SystemDependencyScope; @@ -89,9 +90,10 @@ *

Managed Bits and Graph Transformations

*

* When a {@link org.eclipse.aether.graph.DependencyNode} becomes "managed" by any property - * provided from this manager, {@link org.eclipse.aether.graph.DependencyNode#getManagedBits()} + * provided from this manager, {@link org.eclipse.aether.graph.DependencyNode#isManagedSubject(DependencyManagementSubject)} + * and {@link org.eclipse.aether.graph.DependencyNode#isManagedSubjectEnforced(DependencyManagementSubject)} * will carry this information for the given property. Later graph transformations will abstain - * from modifying these properties of marked nodes (assuming the node already has the property + * from modifying these properties of marked enforced nodes (assuming the node already has the property * set to what it should have). Sometimes this is unwanted, especially for properties that need * to be inherited in the graph (values derived from parent-child context of the actual node, * like "scope" or "optional"). From 9b62d43b3b4040e750f27d240cef02b20aa6be1f Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 2 Oct 2025 12:42:56 +0200 Subject: [PATCH 06/13] Drop this method --- .../aether/graph/DefaultDependencyNode.java | 14 +++++++++++++- .../org/eclipse/aether/graph/DependencyNode.java | 7 ------- 2 files changed, 13 insertions(+), 8 deletions(-) diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java index 545ed2c1c..2a2ae321d 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java @@ -104,7 +104,19 @@ public DefaultDependencyNode(DependencyNode node) { children = new ArrayList<>(0); setAliases(node.getAliases()); setRequestContext(node.getRequestContext()); - setManagedSubjects(node.getManagedSubjects()); + + HashMap managedSubjects = new HashMap<>(); + for (DependencyManagementSubject subject : DependencyManagementSubject.values()) { + if (node.isManagedSubject(subject)) { + managedSubjects.put(subject, node.isManagedSubjectEnforced(subject)); + } + } + if (managedSubjects.isEmpty()) { + setManagedSubjects(null); + } else { + setManagedSubjects(managedSubjects); + } + setRelocations(node.getRelocations()); setRepositories(node.getRepositories()); setVersion(node.getVersion()); diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java index 384e5f7af..82976ee1d 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -184,13 +184,6 @@ public interface DependencyNode { @Deprecated int getManagedBits(); - /** - * Returns what kind of management was applied to this node. - * - * @since 2.0.13 - */ - Map getManagedSubjects(); - /** * Returns {@code true} if given subject is managed. * From 8e917e63e462c79d17f01f33015861d5341e23c3 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Thu, 2 Oct 2025 12:47:09 +0200 Subject: [PATCH 07/13] Drop this --- .../java/org/eclipse/aether/graph/DefaultDependencyNode.java | 5 ----- 1 file changed, 5 deletions(-) diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java index 2a2ae321d..104e60c04 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java @@ -272,11 +272,6 @@ public void setManagedSubjects(Map managed } } - @Override - public Map getManagedSubjects() { - return managedSubjects; - } - @Override public boolean isManagedSubject(DependencyManagementSubject subject) { return managedSubjects.containsKey(subject); From dd796f6c1d4a5b9d8a19eafc02ab7ccbea27ca78 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Sun, 5 Oct 2025 16:59:52 +0200 Subject: [PATCH 08/13] Simplify --- .../collection/DependencyManagement.java | 165 +++++++++++++----- .../aether/graph/DefaultDependencyNode.java | 23 +-- .../graph/DependencyManagementRule.java | 161 ----------------- .../graph/DependencyManagementSubject.java | 32 ---- .../eclipse/aether/graph/DependencyNode.java | 11 +- .../impl/collect/PremanagedDependency.java | 96 +++++----- .../test/util/DependencyGraphParser.java | 8 +- .../manager/AbstractDependencyManager.java | 47 ++--- .../graph/manager/DependencyManagerUtils.java | 12 +- .../transformer/ClassicConflictResolver.java | 6 +- .../transformer/PathConflictResolver.java | 6 +- .../graph/manager/DependencyManagerTest.java | 2 - 12 files changed, 219 insertions(+), 350 deletions(-) delete mode 100644 maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java delete mode 100644 maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java 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 8d6eed9e5..3c1ed4ebb 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 @@ -19,55 +19,41 @@ package org.eclipse.aether.collection; import java.util.Collection; -import java.util.List; +import java.util.HashMap; import java.util.Map; -import org.eclipse.aether.graph.DependencyManagementRule; import org.eclipse.aether.graph.Exclusion; -import static java.util.Objects.requireNonNull; - /** * The management updates to apply to a dependency. * * @see DependencyManager#manageDependency(org.eclipse.aether.graph.Dependency) */ public final class DependencyManagement { - private final List> rules; - - private String version; - - private String scope; - - private Boolean optional; - - private Collection exclusions; - - private Map properties; - /** - * Creates an empty management update. - * - * @deprecated + * Enumeration of manageable attributes, attributes that can be subjected to dependency management. */ - @Deprecated - public DependencyManagement() { - // enables default constructor - this.rules = null; + public enum Subject { + VERSION, + SCOPE, + OPTIONAL, + PROPERTIES, + EXCLUSIONS } + private final Map managedValues; + private final Map managedEnforced; + /** - * Creates instance with given rules. + * Creates an empty management update. */ - public DependencyManagement(List> rules) { - this.rules = requireNonNull(rules); + public DependencyManagement() { + this.managedValues = new HashMap<>(); + this.managedEnforced = new HashMap<>(); } - /** - * Returns the {@link DependencyManagementRule} or {@code null}. - */ - public List> getRules() { - return rules; + public boolean isSubjectEnforced(Subject subject) { + return managedEnforced.getOrDefault(subject, false); } /** @@ -76,9 +62,8 @@ public List> getRules() { * @return The new version or {@code null} if the version is not managed and the existing dependency version should * remain unchanged. */ - @Deprecated public String getVersion() { - return version; + return (String) managedValues.get(Subject.VERSION); } /** @@ -86,10 +71,28 @@ public String getVersion() { * * @param version The new version, may be {@code null} if the version is not managed. * @return This management update for chaining, never {@code null}. + * @deprecated Use {@link #setVersion(String, boolean)} instead. */ @Deprecated public DependencyManagement setVersion(String version) { - this.version = version; + return setVersion(version, true); + } + + /** + * Sets the new version to apply to the dependency. + * + * @param version The new version, may be {@code null} if the version is not managed. + * @param enforced The enforcement of new value. + * @return This management update for chaining, never {@code null}. + */ + public DependencyManagement setVersion(String version, boolean enforced) { + if (version == null) { + this.managedValues.remove(Subject.VERSION); + this.managedEnforced.remove(Subject.VERSION); + } else { + this.managedValues.put(Subject.VERSION, version); + this.managedEnforced.put(Subject.VERSION, enforced); + } return this; } @@ -99,9 +102,8 @@ public DependencyManagement setVersion(String version) { * @return The new scope or {@code null} if the scope is not managed and the existing dependency scope should remain * unchanged. */ - @Deprecated public String getScope() { - return scope; + return (String) managedValues.get(Subject.SCOPE); } /** @@ -112,7 +114,24 @@ public String getScope() { */ @Deprecated public DependencyManagement setScope(String scope) { - this.scope = scope; + return setScope(scope, true); + } + + /** + * Sets the new scope to apply to the dependency. + * + * @param scope The new scope, may be {@code null} if the scope is not managed. + * @param enforced The enforcement of new value. + * @return This management update for chaining, never {@code null}. + */ + public DependencyManagement setScope(String scope, boolean enforced) { + if (scope == null) { + this.managedValues.remove(Subject.SCOPE); + this.managedEnforced.remove(Subject.SCOPE); + } else { + this.managedValues.put(Subject.SCOPE, scope); + this.managedEnforced.put(Subject.SCOPE, enforced); + } return this; } @@ -122,9 +141,8 @@ public DependencyManagement setScope(String scope) { * @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. */ - @Deprecated public Boolean getOptional() { - return optional; + return (Boolean) managedValues.get(Subject.OPTIONAL); } /** @@ -135,7 +153,24 @@ public Boolean getOptional() { */ @Deprecated public DependencyManagement setOptional(Boolean optional) { - this.optional = optional; + return setOptional(optional, true); + } + + /** + * 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. + * @param enforced The enforcement of new value. + * @return This management update for chaining, never {@code null}. + */ + public DependencyManagement setOptional(Boolean optional, boolean enforced) { + if (optional == null) { + this.managedValues.remove(Subject.OPTIONAL); + this.managedEnforced.remove(Subject.OPTIONAL); + } else { + this.managedValues.put(Subject.OPTIONAL, optional); + this.managedEnforced.put(Subject.OPTIONAL, enforced); + } return this; } @@ -147,9 +182,9 @@ public DependencyManagement setOptional(Boolean optional) { * @return The new exclusions or {@code null} if the exclusions are not managed and the existing dependency * exclusions should remain unchanged. */ - @Deprecated + @SuppressWarnings("unchecked") public Collection getExclusions() { - return exclusions; + return (Collection) managedValues.get(Subject.EXCLUSIONS); } /** @@ -162,7 +197,26 @@ public Collection getExclusions() { */ @Deprecated public DependencyManagement setExclusions(Collection exclusions) { - this.exclusions = exclusions; + return setExclusions(exclusions, true); + } + + /** + * 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. + * @param enforced The enforcement of new value. + * @return This management update for chaining, never {@code null}. + */ + public DependencyManagement setExclusions(Collection exclusions, boolean enforced) { + if (exclusions == null) { + this.managedValues.remove(Subject.EXCLUSIONS); + this.managedEnforced.remove(Subject.EXCLUSIONS); + } else { + this.managedValues.put(Subject.EXCLUSIONS, exclusions); + this.managedEnforced.put(Subject.EXCLUSIONS, enforced); + } return this; } @@ -174,9 +228,9 @@ public DependencyManagement setExclusions(Collection exclusions) { * @return The new artifact properties or {@code null} if the properties are not managed and the existing properties * should remain unchanged. */ - @Deprecated + @SuppressWarnings("unchecked") public Map getProperties() { - return properties; + return (Map) managedValues.get(Subject.PROPERTIES); } /** @@ -189,7 +243,26 @@ public Map getProperties() { */ @Deprecated public DependencyManagement setProperties(Map properties) { - this.properties = properties; + return setProperties(properties, true); + } + + /** + * 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. + * @param enforced The enforcement of new value. + * @return This management update for chaining, never {@code null}. + */ + public DependencyManagement setProperties(Map properties, boolean enforced) { + if (properties == null) { + this.managedValues.remove(Subject.PROPERTIES); + this.managedEnforced.remove(Subject.PROPERTIES); + } else { + this.managedValues.put(Subject.PROPERTIES, properties); + this.managedEnforced.put(Subject.PROPERTIES, enforced); + } return this; } } diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java index 104e60c04..fdfdddf64 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DefaultDependencyNode.java @@ -26,6 +26,7 @@ import java.util.Map; import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.DependencyManagement; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.version.Version; import org.eclipse.aether.version.VersionConstraint; @@ -51,7 +52,7 @@ public final class DefaultDependencyNode implements DependencyNode { private Version version; - private Map managedSubjects = Collections.emptyMap(); + private Map managedSubjects = Collections.emptyMap(); private List repositories; @@ -105,8 +106,8 @@ public DefaultDependencyNode(DependencyNode node) { setAliases(node.getAliases()); setRequestContext(node.getRequestContext()); - HashMap managedSubjects = new HashMap<>(); - for (DependencyManagementSubject subject : DependencyManagementSubject.values()) { + HashMap managedSubjects = new HashMap<>(); + for (DependencyManagement.Subject subject : DependencyManagement.Subject.values()) { if (node.isManagedSubject(subject)) { managedSubjects.put(subject, node.isManagedSubjectEnforced(subject)); } @@ -241,19 +242,19 @@ public void setOptional(Boolean optional) { @Override public int getManagedBits() { byte res = 0; - if (isManagedSubject(DependencyManagementSubject.VERSION)) { + if (isManagedSubject(DependencyManagement.Subject.VERSION)) { res |= DependencyNode.MANAGED_VERSION; } - if (isManagedSubject(DependencyManagementSubject.SCOPE)) { + if (isManagedSubject(DependencyManagement.Subject.SCOPE)) { res |= DependencyNode.MANAGED_SCOPE; } - if (isManagedSubject(DependencyManagementSubject.OPTIONAL)) { + if (isManagedSubject(DependencyManagement.Subject.OPTIONAL)) { res |= DependencyNode.MANAGED_OPTIONAL; } - if (isManagedSubject(DependencyManagementSubject.PROPERTIES)) { + if (isManagedSubject(DependencyManagement.Subject.PROPERTIES)) { res |= DependencyNode.MANAGED_PROPERTIES; } - if (isManagedSubject(DependencyManagementSubject.EXCLUSIONS)) { + if (isManagedSubject(DependencyManagement.Subject.EXCLUSIONS)) { res |= DependencyNode.MANAGED_EXCLUSIONS; } return res; @@ -264,7 +265,7 @@ public void setManagedBits(int managedBits) { throw new IllegalArgumentException("bits are not supported"); } - public void setManagedSubjects(Map managedSubjects) { + public void setManagedSubjects(Map managedSubjects) { if (managedSubjects == null) { this.managedSubjects = Collections.emptyMap(); } else { @@ -273,12 +274,12 @@ public void setManagedSubjects(Map managed } @Override - public boolean isManagedSubject(DependencyManagementSubject subject) { + public boolean isManagedSubject(DependencyManagement.Subject subject) { return managedSubjects.containsKey(subject); } @Override - public boolean isManagedSubjectEnforced(DependencyManagementSubject subject) { + public boolean isManagedSubjectEnforced(DependencyManagement.Subject subject) { return managedSubjects.getOrDefault(subject, false); } diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java deleted file mode 100644 index 11a982b26..000000000 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementRule.java +++ /dev/null @@ -1,161 +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.graph; - -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Objects; -import java.util.function.UnaryOperator; - -import static java.util.Objects.requireNonNull; - -/** - * Represents a dependency management rule, a managed value of given {@link DependencyManagementSubject}. - * - * @param the type of subject rule operates on. - * @since 2.0.13 - */ -public class DependencyManagementRule implements UnaryOperator { - public static ManagedVersion managedVersion(String version, boolean enforcing) { - return new ManagedVersion(version, enforcing); - } - - public static ManagedScope managedScope(String scope, boolean enforcing) { - return new ManagedScope(scope, enforcing); - } - - public static ManagedOptional managedOptional(Boolean optional, boolean enforcing) { - return new ManagedOptional(optional, enforcing); - } - - public static ManagedPropertiesPut managedPropertiesPut(Map properties, boolean enforcing) { - return new ManagedPropertiesPut(properties, enforcing); - } - - public static ManagedPropertiesRemove managedPropertiesRemove(Collection keys, boolean enforcing) { - return new ManagedPropertiesRemove(keys, enforcing); - } - - public static ManagedExclusions managedExclusions(Collection exclusions, boolean enforcing) { - return new ManagedExclusions(exclusions, enforcing); - } - - private final T value; - - private final DependencyManagementSubject subject; - - private final boolean enforcing; - - private final UnaryOperator operator; - - private final int hashCode; - - protected DependencyManagementRule( - T value, DependencyManagementSubject subject, boolean enforcing, UnaryOperator operator) { - this.value = requireNonNull(value); - this.subject = requireNonNull(subject); - this.enforcing = enforcing; - this.operator = requireNonNull(operator); - - this.hashCode = Objects.hash(value, subject, enforcing); - } - - public T getValue() { - return value; - } - - public DependencyManagementSubject getSubject() { - return subject; - } - - public boolean isEnforcing() { - return enforcing; - } - - @Override - public Dependency apply(Dependency dependency) { - requireNonNull(dependency); - return operator.apply(dependency); - } - - @Override - public boolean equals(Object o) { - if (!(o instanceof DependencyManagementRule)) { - return false; - } - DependencyManagementRule that = (DependencyManagementRule) o; - return enforcing == that.enforcing && Objects.equals(value, that.value) && subject == that.subject; - } - - @Override - public int hashCode() { - return hashCode; - } - - public static final class ManagedVersion extends DependencyManagementRule { - private ManagedVersion(String value, boolean enforcing) { - super( - value, - DependencyManagementSubject.VERSION, - enforcing, - d -> d.setArtifact(d.getArtifact().setVersion(value))); - } - } - - public static final class ManagedScope extends DependencyManagementRule { - private ManagedScope(String value, boolean enforcing) { - super(value, DependencyManagementSubject.SCOPE, enforcing, d -> d.setScope(value)); - } - } - - public static final class ManagedOptional extends DependencyManagementRule { - private ManagedOptional(Boolean value, boolean enforcing) { - super(value, DependencyManagementSubject.OPTIONAL, enforcing, d -> d.setOptional(value)); - } - } - - public static final class ManagedPropertiesPut extends DependencyManagementRule> { - private ManagedPropertiesPut(Map value, boolean enforcing) { - super(value, DependencyManagementSubject.PROPERTIES, enforcing, d -> { - HashMap properties = - new HashMap<>(d.getArtifact().getProperties()); - properties.putAll(value); - return d.setArtifact(d.getArtifact().setProperties(properties)); - }); - } - } - - public static final class ManagedPropertiesRemove extends DependencyManagementRule> { - private ManagedPropertiesRemove(Collection value, boolean enforcing) { - super(value, DependencyManagementSubject.PROPERTIES, enforcing, d -> { - HashMap properties = - new HashMap<>(d.getArtifact().getProperties()); - value.forEach(properties::remove); - return d.setArtifact(d.getArtifact().setProperties(properties)); - }); - } - } - - public static final class ManagedExclusions extends DependencyManagementRule> { - private ManagedExclusions(Collection value, boolean enforcing) { - super(value, DependencyManagementSubject.EXCLUSIONS, enforcing, d -> d.setExclusions(value)); - } - } -} diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java deleted file mode 100644 index 1f0645e7d..000000000 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyManagementSubject.java +++ /dev/null @@ -1,32 +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.graph; - -/** - * Represents a dependency management subject, a managed attribute of dependency. - * - * @since 2.0.13 - */ -public enum DependencyManagementSubject { - VERSION, - SCOPE, - OPTIONAL, - PROPERTIES, - EXCLUSIONS -} diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java index 82976ee1d..9451488df 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -23,6 +23,7 @@ import java.util.Map; import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.DependencyManagement; import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.version.Version; import org.eclipse.aether.version.VersionConstraint; @@ -187,18 +188,18 @@ public interface DependencyNode { /** * Returns {@code true} if given subject is managed. * - * @see DependencyManagementRule#isEnforcing() + * @see org.eclipse.aether.collection.DependencyManagement.Subject * @since 2.0.13 */ - boolean isManagedSubject(DependencyManagementSubject subject); + boolean isManagedSubject(DependencyManagement.Subject subject); /** - * Returns {@code true} if given subject is managed with {@link DependencyManagementRule#isEnforcing()} on this node. + * Returns {@code true} if given subject is managed with enforcing modality on this node. * - * @see DependencyManagementRule#isEnforcing() + * @see org.eclipse.aether.collection.DependencyManagement.Subject * @since 2.0.13 */ - boolean isManagedSubjectEnforced(DependencyManagementSubject subject); + boolean isManagedSubjectEnforced(DependencyManagement.Subject subject); /** * Gets the remote repositories from which this node's artifact shall be resolved. diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java index c5766759d..0dcdc9333 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java @@ -29,8 +29,6 @@ import org.eclipse.aether.collection.DependencyManager; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.graph.DependencyManagementRule; -import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.Exclusion; import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; @@ -58,7 +56,7 @@ public class PremanagedDependency { /** * @since 2.0.13 */ - final Map managedSubjects; + final Map managedSubjects; final Dependency managedDependency; @@ -71,7 +69,7 @@ public class PremanagedDependency { Boolean premanagedOptional, Collection premanagedExclusions, Map premanagedProperties, - Map managedSubjects, + Map managedSubjects, Dependency managedDependency, boolean premanagedState) { this.premanagedVersion = premanagedVersion; @@ -96,7 +94,7 @@ public static PremanagedDependency create( boolean premanagedState) { DependencyManagement management = depManager != null ? depManager.manageDependency(dependency) : null; - Map managedSubjects = new HashMap<>(); + Map managedSubjects = new HashMap<>(); String premanagedVersion = null; String premanagedScope = null; Boolean premanagedOptional = null; @@ -104,58 +102,42 @@ public static PremanagedDependency create( Map premanagedProperties = null; if (management != null) { - if (management.getRules() != null) { - for (DependencyManagementRule rule : management.getRules()) { - DependencyManagementSubject subject = rule.getSubject(); - if (subject == DependencyManagementSubject.VERSION) { - if (disableVersionManagement) { - continue; - } - premanagedVersion = dependency.getArtifact().getVersion(); - } else if (subject == DependencyManagementSubject.SCOPE) { - premanagedScope = dependency.getScope(); - } else if (subject == DependencyManagementSubject.OPTIONAL) { - premanagedOptional = dependency.isOptional(); - } else if (subject == DependencyManagementSubject.PROPERTIES) { - premanagedProperties = dependency.getArtifact().getProperties(); - } else if (subject == DependencyManagementSubject.EXCLUSIONS) { - premanagedExclusions = dependency.getExclusions(); - } else { - throw new IllegalArgumentException("unknown subject " + subject); - } - dependency = rule.apply(dependency); - managedSubjects.put(subject, rule.isEnforcing()); - } - } else { - // legacy path: here there are no means to distinguish "management" as enforced or advised (so all are - // enforced) - if (management.getVersion() != null && !disableVersionManagement) { - Artifact artifact = dependency.getArtifact(); - premanagedVersion = artifact.getVersion(); - dependency = dependency.setArtifact(artifact.setVersion(management.getVersion())); - managedSubjects.put(DependencyManagementSubject.VERSION, true); - } - if (management.getProperties() != null) { - Artifact artifact = dependency.getArtifact(); - premanagedProperties = artifact.getProperties(); - dependency = dependency.setArtifact(artifact.setProperties(management.getProperties())); - managedSubjects.put(DependencyManagementSubject.PROPERTIES, true); - } - if (management.getScope() != null) { - premanagedScope = dependency.getScope(); - dependency = dependency.setScope(management.getScope()); - managedSubjects.put(DependencyManagementSubject.SCOPE, true); - } - if (management.getOptional() != null) { - premanagedOptional = dependency.isOptional(); - dependency = dependency.setOptional(management.getOptional()); - managedSubjects.put(DependencyManagementSubject.OPTIONAL, true); - } - if (management.getExclusions() != null) { - premanagedExclusions = dependency.getExclusions(); - dependency = dependency.setExclusions(management.getExclusions()); - managedSubjects.put(DependencyManagementSubject.EXCLUSIONS, true); - } + if (management.getVersion() != null && !disableVersionManagement) { + Artifact artifact = dependency.getArtifact(); + premanagedVersion = artifact.getVersion(); + dependency = dependency.setArtifact(artifact.setVersion(management.getVersion())); + managedSubjects.put( + DependencyManagement.Subject.VERSION, + management.isSubjectEnforced(DependencyManagement.Subject.VERSION)); + } + if (management.getProperties() != null) { + Artifact artifact = dependency.getArtifact(); + premanagedProperties = artifact.getProperties(); + dependency = dependency.setArtifact(artifact.setProperties(management.getProperties())); + managedSubjects.put( + DependencyManagement.Subject.PROPERTIES, + management.isSubjectEnforced(DependencyManagement.Subject.PROPERTIES)); + } + if (management.getScope() != null) { + premanagedScope = dependency.getScope(); + dependency = dependency.setScope(management.getScope()); + managedSubjects.put( + DependencyManagement.Subject.SCOPE, + management.isSubjectEnforced(DependencyManagement.Subject.SCOPE)); + } + if (management.getOptional() != null) { + premanagedOptional = dependency.isOptional(); + dependency = dependency.setOptional(management.getOptional()); + managedSubjects.put( + DependencyManagement.Subject.OPTIONAL, + management.isSubjectEnforced(DependencyManagement.Subject.OPTIONAL)); + } + if (management.getExclusions() != null) { + premanagedExclusions = dependency.getExclusions(); + dependency = dependency.setExclusions(management.getExclusions()); + managedSubjects.put( + DependencyManagement.Subject.EXCLUSIONS, + management.isSubjectEnforced(DependencyManagement.Subject.EXCLUSIONS)); } } diff --git a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java index 25216912a..944808104 100644 --- a/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java +++ b/maven-resolver-test-util/src/main/java/org/eclipse/aether/internal/test/util/DependencyGraphParser.java @@ -36,9 +36,9 @@ import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.artifact.DefaultArtifact; +import org.eclipse.aether.collection.DependencyManagement; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.version.InvalidVersionSpecificationException; import org.eclipse.aether.version.VersionScheme; @@ -292,13 +292,13 @@ private DependencyNode build(DependencyNode parent, LineContext ctx, boolean isR DefaultArtifact artifact = new DefaultArtifact(def.coords, def.properties); Dependency dependency = new Dependency(artifact, def.scope, def.optional); node = new DefaultDependencyNode(dependency); - Map managedSubjects = new HashMap<>(); + Map managedSubjects = new HashMap<>(); if (def.premanagedScope != null) { - managedSubjects.put(DependencyManagementSubject.SCOPE, true); + managedSubjects.put(DependencyManagement.Subject.SCOPE, true); node.setData("premanaged.scope", def.premanagedScope); } if (def.premanagedVersion != null) { - managedSubjects.put(DependencyManagementSubject.VERSION, true); + managedSubjects.put(DependencyManagement.Subject.VERSION, true); node.setData("premanaged.version", def.premanagedVersion); } node.setManagedSubjects(managedSubjects); 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 508b5096e..6c933a382 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 @@ -20,19 +20,15 @@ import java.util.ArrayList; import java.util.Collection; -import java.util.Collections; import java.util.HashMap; import java.util.LinkedHashSet; 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.DependencyManagementRule; -import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.Exclusion; import org.eclipse.aether.scope.ScopeManager; import org.eclipse.aether.scope.SystemDependencyScope; @@ -393,7 +389,7 @@ public DependencyManager deriveChildManager(DependencyCollectionContext context) @Override public DependencyManagement manageDependency(Dependency dependency) { requireNonNull(dependency, "dependency cannot be null"); - ArrayList> rules = new ArrayList<>(); + DependencyManagement management = null; Key key = new Key(dependency.getArtifact()); if (isApplied()) { @@ -401,22 +397,27 @@ public DependencyManagement manageDependency(Dependency dependency) { // is managed locally by model builder // apply only rules coming from "higher" levels if (versionOwner != null) { - rules.add(DependencyManagementRule.managedVersion( - versionOwner.managedVersions.get(key), versionOwner.path.isEmpty())); + management = new DependencyManagement(); + management.setVersion(versionOwner.managedVersions.get(key), versionOwner.path.isEmpty()); } AbstractDependencyManager scopeOwner = getManagedScope(key); // is managed locally by model builder // apply only rules coming from "higher" levels if (scopeOwner != null) { + if (management == null) { + management = new DependencyManagement(); + } String managedScope = scopeOwner.managedScopes.get(key); - rules.add(DependencyManagementRule.managedScope(managedScope, scopeOwner.path.isEmpty())); + management.setScope(managedScope, scopeOwner.path.isEmpty()); if (systemDependencyScope != null && !systemDependencyScope.is(managedScope) && systemDependencyScope.getSystemPath(dependency.getArtifact()) != null) { - rules.add(DependencyManagementRule.managedPropertiesRemove( - Collections.singleton(ArtifactProperties.LOCAL_PATH), false)); + HashMap properties = + new HashMap<>(dependency.getArtifact().getProperties()); + systemDependencyScope.setSystemPath(properties, null); + management.setProperties(properties, false); } } @@ -427,9 +428,13 @@ public DependencyManagement manageDependency(Dependency dependency) { || (scopeOwner == null && systemDependencyScope.is(dependency.getScope())))) { AbstractDependencyManager localPathOwner = getManagedLocalPath(key); if (localPathOwner != null) { - HashMap properties = new HashMap<>(); - properties.put(ArtifactProperties.LOCAL_PATH, localPathOwner.managedLocalPaths.get(key)); - rules.add(DependencyManagementRule.managedPropertiesPut(properties, false)); + if (management == null) { + management = new DependencyManagement(); + } + HashMap properties = + new HashMap<>(dependency.getArtifact().getProperties()); + systemDependencyScope.setSystemPath(properties, localPathOwner.managedLocalPaths.get(key)); + management.setProperties(properties, false); } } @@ -437,8 +442,10 @@ public DependencyManagement manageDependency(Dependency dependency) { // apply only rules coming from "higher" levels AbstractDependencyManager optionalOwner = getManagedOptional(key); if (optionalOwner != null) { - rules.add(DependencyManagementRule.managedOptional( - optionalOwner.managedOptionals.get(key), optionalOwner.path.isEmpty())); + if (management == null) { + management = new DependencyManagement(); + } + management.setOptional(optionalOwner.managedOptionals.get(key), optionalOwner.path.isEmpty()); } } @@ -449,15 +456,15 @@ public DependencyManagement manageDependency(Dependency dependency) { // so we merge it here even from same level Collection exclusions = getManagedExclusions(key); if (exclusions != null) { + if (management == null) { + management = new DependencyManagement(); + } Collection result = new LinkedHashSet<>(dependency.getExclusions()); result.addAll(exclusions); - rules.add(DependencyManagementRule.managedExclusions(result, false)); + management.setExclusions(result, false); } - if (rules.isEmpty()) { - return null; - } - return new DependencyManagement(rules); + return management; } /** 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 ca87113ab..685d005f4 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 @@ -23,7 +23,7 @@ import org.eclipse.aether.ConfigurationProperties; import org.eclipse.aether.RepositorySystemSession; -import org.eclipse.aether.graph.DependencyManagementSubject; +import org.eclipse.aether.collection.DependencyManagement; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.graph.Exclusion; @@ -88,7 +88,7 @@ public final class DependencyManagerUtils { * or if {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static String getPremanagedVersion(DependencyNode node) { - if (!node.isManagedSubject(DependencyManagementSubject.VERSION)) { + if (!node.isManagedSubject(DependencyManagement.Subject.VERSION)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_VERSION), String.class); @@ -102,7 +102,7 @@ public static String getPremanagedVersion(DependencyNode node) { * if {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static String getPremanagedScope(DependencyNode node) { - if (!node.isManagedSubject(DependencyManagementSubject.SCOPE)) { + if (!node.isManagedSubject(DependencyManagement.Subject.SCOPE)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_SCOPE), String.class); @@ -116,7 +116,7 @@ public static String getPremanagedScope(DependencyNode node) { * {@link #CONFIG_PROP_VERBOSE} was not enabled */ public static Boolean getPremanagedOptional(DependencyNode node) { - if (!node.isManagedSubject(DependencyManagementSubject.OPTIONAL)) { + if (!node.isManagedSubject(DependencyManagement.Subject.OPTIONAL)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_OPTIONAL), Boolean.class); @@ -132,7 +132,7 @@ public static Boolean getPremanagedOptional(DependencyNode node) { */ @SuppressWarnings("unchecked") public static Collection getPremanagedExclusions(DependencyNode node) { - if (!node.isManagedSubject(DependencyManagementSubject.EXCLUSIONS)) { + if (!node.isManagedSubject(DependencyManagement.Subject.EXCLUSIONS)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_EXCLUSIONS), Collection.class); @@ -148,7 +148,7 @@ public static Collection getPremanagedExclusions(DependencyNode node) */ @SuppressWarnings("unchecked") public static Map getPremanagedProperties(DependencyNode node) { - if (!node.isManagedSubject(DependencyManagementSubject.PROPERTIES)) { + if (!node.isManagedSubject(DependencyManagement.Subject.PROPERTIES)) { return null; } return cast(node.getData().get(NODE_DATA_PREMANAGED_PROPERTIES), Map.class); diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java index 5591af566..4825e433e 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/ClassicConflictResolver.java @@ -33,9 +33,9 @@ import org.eclipse.aether.RepositoryException; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.collection.DependencyGraphTransformationContext; +import org.eclipse.aether.collection.DependencyManagement; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.util.artifact.ArtifactIdUtils; @@ -676,7 +676,7 @@ private DependencyNode parent() { } private String deriveScope(DependencyNode node, String conflictId) throws RepositoryException { - if (node.isManagedSubjectEnforced(DependencyManagementSubject.SCOPE) + if (node.isManagedSubjectEnforced(DependencyManagement.Subject.SCOPE) || (conflictId != null && resolvedIds.containsKey(conflictId))) { return scope(node.getDependency()); } @@ -703,7 +703,7 @@ private boolean deriveOptional(DependencyNode node, String conflictId) { Dependency dep = node.getDependency(); boolean optional = (dep != null) && dep.isOptional(); if (optional - || node.isManagedSubjectEnforced(DependencyManagementSubject.OPTIONAL) + || node.isManagedSubjectEnforced(DependencyManagement.Subject.OPTIONAL) || (conflictId != null && resolvedIds.containsKey(conflictId))) { return optional; } diff --git a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java index a822c9359..519e60873 100644 --- a/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java +++ b/maven-resolver-util/src/main/java/org/eclipse/aether/util/graph/transformer/PathConflictResolver.java @@ -32,9 +32,9 @@ import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.collection.DependencyGraphTransformationContext; +import org.eclipse.aether.collection.DependencyManagement; import org.eclipse.aether.graph.DefaultDependencyNode; import org.eclipse.aether.graph.Dependency; -import org.eclipse.aether.graph.DependencyManagementSubject; import org.eclipse.aether.graph.DependencyNode; import org.eclipse.aether.util.ConfigUtils; import org.eclipse.aether.util.artifact.ArtifactIdUtils; @@ -424,12 +424,12 @@ private void pull(int levels) { private void derive(int levels, boolean winner) throws RepositoryException { if (!winner) { if (this.parent != null) { - if (!dn.isManagedSubjectEnforced(DependencyManagementSubject.SCOPE)) { + if (!dn.isManagedSubjectEnforced(DependencyManagement.Subject.SCOPE)) { ScopeContext context = new ScopeContext(this.parent.scope, this.scope); state.scopeDeriver.deriveScope(context); this.scope = context.derivedScope; } - if (!dn.isManagedSubjectEnforced(DependencyManagementSubject.OPTIONAL)) { + if (!dn.isManagedSubjectEnforced(DependencyManagement.Subject.OPTIONAL)) { if (!this.optional && this.parent.optional) { this.optional = true; } 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 index 412bdab3b..b32b7907e 100644 --- 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 @@ -31,7 +31,6 @@ 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.Disabled; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.*; @@ -39,7 +38,6 @@ /** * UT for {@link DependencyManager} implementations. */ -@Disabled("This is not anymore how dependency manager works") public class DependencyManagerTest { private final Artifact A1 = new DefaultArtifact("test", "a", "", "1"); From 7e3c9c5fab84128337530aff707d173891afdda8 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Sun, 5 Oct 2025 17:33:22 +0200 Subject: [PATCH 09/13] Javadoc --- .../aether/collection/DependencyManagement.java | 16 ++++++++++++++++ .../org/eclipse/aether/graph/DependencyNode.java | 12 ++++++------ 2 files changed, 22 insertions(+), 6 deletions(-) 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 3c1ed4ebb..1b57ab33a 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 @@ -32,6 +32,8 @@ public final class DependencyManagement { /** * Enumeration of manageable attributes, attributes that can be subjected to dependency management. + * + * @since 2.0.13 */ public enum Subject { VERSION, @@ -52,6 +54,11 @@ public DependencyManagement() { this.managedEnforced = new HashMap<>(); } + /** + * Returns {@code true} if passed in subject is managed and is enforced. + * + * @since 2.0.13 + */ public boolean isSubjectEnforced(Subject subject) { return managedEnforced.getOrDefault(subject, false); } @@ -84,6 +91,7 @@ public DependencyManagement setVersion(String version) { * @param version The new version, may be {@code null} if the version is not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. + * @since 2.0.13 */ public DependencyManagement setVersion(String version, boolean enforced) { if (version == null) { @@ -111,6 +119,7 @@ public String getScope() { * * @param scope The new scope, may be {@code null} if the scope is not managed. * @return This management update for chaining, never {@code null}. + * @deprecated Use {@link #setScope(String, boolean)} instead. */ @Deprecated public DependencyManagement setScope(String scope) { @@ -123,6 +132,7 @@ public DependencyManagement setScope(String scope) { * @param scope The new scope, may be {@code null} if the scope is not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. + * @since 2.0.13 */ public DependencyManagement setScope(String scope, boolean enforced) { if (scope == null) { @@ -150,6 +160,7 @@ public Boolean getOptional() { * * @param optional The optional flag, may be {@code null} if the flag is not managed. * @return This management update for chaining, never {@code null}. + * @deprecated Use {@link #setOptional(Boolean, boolean)} instead. */ @Deprecated public DependencyManagement setOptional(Boolean optional) { @@ -162,6 +173,7 @@ public DependencyManagement setOptional(Boolean optional) { * @param optional The optional flag, may be {@code null} if the flag is not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. + * @since 2.0.13 */ public DependencyManagement setOptional(Boolean optional, boolean enforced) { if (optional == null) { @@ -194,6 +206,7 @@ public Collection getExclusions() { * * @param exclusions The new exclusions, may be {@code null} if the exclusions are not managed. * @return This management update for chaining, never {@code null}. + * @deprecated Use {@link #setExclusions(Collection, boolean)} instead. */ @Deprecated public DependencyManagement setExclusions(Collection exclusions) { @@ -208,6 +221,7 @@ public DependencyManagement setExclusions(Collection exclusions) { * @param exclusions The new exclusions, may be {@code null} if the exclusions are not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. + * @since 2.0.13 */ public DependencyManagement setExclusions(Collection exclusions, boolean enforced) { if (exclusions == null) { @@ -240,6 +254,7 @@ public Map getProperties() { * * @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}. + * @deprecated Use {@link #setProperties(Map, boolean)} instead. */ @Deprecated public DependencyManagement setProperties(Map properties) { @@ -254,6 +269,7 @@ public DependencyManagement setProperties(Map properties) { * @param properties The new artifact properties, may be {@code null} if the properties are not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. + * @since 2.0.13 */ public DependencyManagement setProperties(Map properties, boolean enforced) { if (properties == null) { diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java index 9451488df..e70d10cec 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -43,7 +43,7 @@ public interface DependencyNode { * A bit flag indicating the dependency version was subject to dependency management * * @see #getManagedBits() - * @deprecated + * @deprecated Use {@link #isManagedSubject(DependencyManagement.Subject)} and {@link #isManagedSubjectEnforced(DependencyManagement.Subject)} instead. */ @Deprecated int MANAGED_VERSION = 0x01; @@ -52,7 +52,7 @@ public interface DependencyNode { * A bit flag indicating the dependency scope was subject to dependency management * * @see #getManagedBits() - * @deprecated + * @deprecated Use {@link #isManagedSubject(DependencyManagement.Subject)} and {@link #isManagedSubjectEnforced(DependencyManagement.Subject)} instead. */ @Deprecated int MANAGED_SCOPE = 0x02; @@ -61,7 +61,7 @@ public interface DependencyNode { * A bit flag indicating the optional flag was subject to dependency management * * @see #getManagedBits() - * @deprecated + * @deprecated Use {@link #isManagedSubject(DependencyManagement.Subject)} and {@link #isManagedSubjectEnforced(DependencyManagement.Subject)} instead. */ @Deprecated int MANAGED_OPTIONAL = 0x04; @@ -70,7 +70,7 @@ public interface DependencyNode { * A bit flag indicating the artifact properties were subject to dependency management * * @see #getManagedBits() - * @deprecated + * @deprecated Use {@link #isManagedSubject(DependencyManagement.Subject)} and {@link #isManagedSubjectEnforced(DependencyManagement.Subject)} instead. */ @Deprecated int MANAGED_PROPERTIES = 0x08; @@ -79,7 +79,7 @@ public interface DependencyNode { * A bit flag indicating the exclusions were subject to dependency management * * @see #getManagedBits() - * @deprecated + * @deprecated Use {@link #isManagedSubject(DependencyManagement.Subject)} and {@link #isManagedSubjectEnforced(DependencyManagement.Subject)} instead. */ @Deprecated int MANAGED_EXCLUSIONS = 0x10; @@ -180,7 +180,7 @@ public interface DependencyNode { * @return A bit field containing any of the bits {@link #MANAGED_VERSION}, {@link #MANAGED_SCOPE}, * {@link #MANAGED_OPTIONAL}, {@link #MANAGED_PROPERTIES} and {@link #MANAGED_EXCLUSIONS} if the * corresponding attribute was set via dependency management. - * @deprecated + * @deprecated Use {@link #isManagedSubject(DependencyManagement.Subject)} and {@link #isManagedSubjectEnforced(DependencyManagement.Subject)} instead. */ @Deprecated int getManagedBits(); From 8269881d2c4284e240ba3125fb8180fb3b21c1a1 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Mon, 6 Oct 2025 11:15:36 +0200 Subject: [PATCH 10/13] Lessen irrelevant changes --- .../impl/collect/PremanagedDependency.java | 34 +++++++++---------- 1 file changed, 17 insertions(+), 17 deletions(-) diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java index 0dcdc9333..3f1636a33 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java @@ -92,7 +92,7 @@ public static PremanagedDependency create( Dependency dependency, boolean disableVersionManagement, boolean premanagedState) { - DependencyManagement management = depManager != null ? depManager.manageDependency(dependency) : null; + DependencyManagement depMngt = depManager != null ? depManager.manageDependency(dependency) : null; Map managedSubjects = new HashMap<>(); String premanagedVersion = null; @@ -101,43 +101,43 @@ public static PremanagedDependency create( Collection premanagedExclusions = null; Map premanagedProperties = null; - if (management != null) { - if (management.getVersion() != null && !disableVersionManagement) { + if (depMngt != null) { + if (depMngt.getVersion() != null && !disableVersionManagement) { Artifact artifact = dependency.getArtifact(); premanagedVersion = artifact.getVersion(); - dependency = dependency.setArtifact(artifact.setVersion(management.getVersion())); + dependency = dependency.setArtifact(artifact.setVersion(depMngt.getVersion())); managedSubjects.put( DependencyManagement.Subject.VERSION, - management.isSubjectEnforced(DependencyManagement.Subject.VERSION)); + depMngt.isSubjectEnforced(DependencyManagement.Subject.VERSION)); } - if (management.getProperties() != null) { + if (depMngt.getProperties() != null) { Artifact artifact = dependency.getArtifact(); premanagedProperties = artifact.getProperties(); - dependency = dependency.setArtifact(artifact.setProperties(management.getProperties())); + dependency = dependency.setArtifact(artifact.setProperties(depMngt.getProperties())); managedSubjects.put( DependencyManagement.Subject.PROPERTIES, - management.isSubjectEnforced(DependencyManagement.Subject.PROPERTIES)); + depMngt.isSubjectEnforced(DependencyManagement.Subject.PROPERTIES)); } - if (management.getScope() != null) { + if (depMngt.getScope() != null) { premanagedScope = dependency.getScope(); - dependency = dependency.setScope(management.getScope()); + dependency = dependency.setScope(depMngt.getScope()); managedSubjects.put( DependencyManagement.Subject.SCOPE, - management.isSubjectEnforced(DependencyManagement.Subject.SCOPE)); + depMngt.isSubjectEnforced(DependencyManagement.Subject.SCOPE)); } - if (management.getOptional() != null) { + if (depMngt.getOptional() != null) { premanagedOptional = dependency.isOptional(); - dependency = dependency.setOptional(management.getOptional()); + dependency = dependency.setOptional(depMngt.getOptional()); managedSubjects.put( DependencyManagement.Subject.OPTIONAL, - management.isSubjectEnforced(DependencyManagement.Subject.OPTIONAL)); + depMngt.isSubjectEnforced(DependencyManagement.Subject.OPTIONAL)); } - if (management.getExclusions() != null) { + if (depMngt.getExclusions() != null) { premanagedExclusions = dependency.getExclusions(); - dependency = dependency.setExclusions(management.getExclusions()); + dependency = dependency.setExclusions(depMngt.getExclusions()); managedSubjects.put( DependencyManagement.Subject.EXCLUSIONS, - management.isSubjectEnforced(DependencyManagement.Subject.EXCLUSIONS)); + depMngt.isSubjectEnforced(DependencyManagement.Subject.EXCLUSIONS)); } } From 9807b9eeba28c4911d683414ce5eb47a5734a908 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 7 Oct 2025 11:45:40 +0200 Subject: [PATCH 11/13] Updates --- .../collection/DependencyManagement.java | 27 ++++++++++++------- .../eclipse/aether/graph/DependencyNode.java | 4 +-- .../impl/collect/PremanagedDependency.java | 10 +++---- 3 files changed, 25 insertions(+), 16 deletions(-) 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 1b57ab33a..3779c02ec 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 @@ -33,7 +33,7 @@ public final class DependencyManagement { /** * Enumeration of manageable attributes, attributes that can be subjected to dependency management. * - * @since 2.0.13 + * @since 2.0.14 */ public enum Subject { VERSION, @@ -54,13 +54,22 @@ public DependencyManagement() { this.managedEnforced = new HashMap<>(); } + /** + * Returns {@code true} if passed in subject is managed. + * + * @since 2.0.14 + */ + public boolean isManagedSubject(Subject subject) { + return managedValues.containsKey(subject); + } + /** * Returns {@code true} if passed in subject is managed and is enforced. * - * @since 2.0.13 + * @since 2.0.14 */ - public boolean isSubjectEnforced(Subject subject) { - return managedEnforced.getOrDefault(subject, false); + public boolean isManagedSubjectEnforced(Subject subject) { + return isManagedSubject(subject) && managedEnforced.getOrDefault(subject, false); } /** @@ -91,7 +100,7 @@ public DependencyManagement setVersion(String version) { * @param version The new version, may be {@code null} if the version is not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. - * @since 2.0.13 + * @since 2.0.14 */ public DependencyManagement setVersion(String version, boolean enforced) { if (version == null) { @@ -132,7 +141,7 @@ public DependencyManagement setScope(String scope) { * @param scope The new scope, may be {@code null} if the scope is not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. - * @since 2.0.13 + * @since 2.0.14 */ public DependencyManagement setScope(String scope, boolean enforced) { if (scope == null) { @@ -173,7 +182,7 @@ public DependencyManagement setOptional(Boolean optional) { * @param optional The optional flag, may be {@code null} if the flag is not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. - * @since 2.0.13 + * @since 2.0.14 */ public DependencyManagement setOptional(Boolean optional, boolean enforced) { if (optional == null) { @@ -221,7 +230,7 @@ public DependencyManagement setExclusions(Collection exclusions) { * @param exclusions The new exclusions, may be {@code null} if the exclusions are not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. - * @since 2.0.13 + * @since 2.0.14 */ public DependencyManagement setExclusions(Collection exclusions, boolean enforced) { if (exclusions == null) { @@ -269,7 +278,7 @@ public DependencyManagement setProperties(Map properties) { * @param properties The new artifact properties, may be {@code null} if the properties are not managed. * @param enforced The enforcement of new value. * @return This management update for chaining, never {@code null}. - * @since 2.0.13 + * @since 2.0.14 */ public DependencyManagement setProperties(Map properties, boolean enforced) { if (properties == null) { diff --git a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java index e70d10cec..8a809d4e1 100644 --- a/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java +++ b/maven-resolver-api/src/main/java/org/eclipse/aether/graph/DependencyNode.java @@ -189,7 +189,7 @@ public interface DependencyNode { * Returns {@code true} if given subject is managed. * * @see org.eclipse.aether.collection.DependencyManagement.Subject - * @since 2.0.13 + * @since 2.0.14 */ boolean isManagedSubject(DependencyManagement.Subject subject); @@ -197,7 +197,7 @@ public interface DependencyNode { * Returns {@code true} if given subject is managed with enforcing modality on this node. * * @see org.eclipse.aether.collection.DependencyManagement.Subject - * @since 2.0.13 + * @since 2.0.14 */ boolean isManagedSubjectEnforced(DependencyManagement.Subject subject); diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java index 3f1636a33..d2e3d33ac 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java @@ -108,7 +108,7 @@ public static PremanagedDependency create( dependency = dependency.setArtifact(artifact.setVersion(depMngt.getVersion())); managedSubjects.put( DependencyManagement.Subject.VERSION, - depMngt.isSubjectEnforced(DependencyManagement.Subject.VERSION)); + depMngt.isManagedSubjectEnforced(DependencyManagement.Subject.VERSION)); } if (depMngt.getProperties() != null) { Artifact artifact = dependency.getArtifact(); @@ -116,28 +116,28 @@ public static PremanagedDependency create( dependency = dependency.setArtifact(artifact.setProperties(depMngt.getProperties())); managedSubjects.put( DependencyManagement.Subject.PROPERTIES, - depMngt.isSubjectEnforced(DependencyManagement.Subject.PROPERTIES)); + depMngt.isManagedSubjectEnforced(DependencyManagement.Subject.PROPERTIES)); } if (depMngt.getScope() != null) { premanagedScope = dependency.getScope(); dependency = dependency.setScope(depMngt.getScope()); managedSubjects.put( DependencyManagement.Subject.SCOPE, - depMngt.isSubjectEnforced(DependencyManagement.Subject.SCOPE)); + depMngt.isManagedSubjectEnforced(DependencyManagement.Subject.SCOPE)); } if (depMngt.getOptional() != null) { premanagedOptional = dependency.isOptional(); dependency = dependency.setOptional(depMngt.getOptional()); managedSubjects.put( DependencyManagement.Subject.OPTIONAL, - depMngt.isSubjectEnforced(DependencyManagement.Subject.OPTIONAL)); + depMngt.isManagedSubjectEnforced(DependencyManagement.Subject.OPTIONAL)); } if (depMngt.getExclusions() != null) { premanagedExclusions = dependency.getExclusions(); dependency = dependency.setExclusions(depMngt.getExclusions()); managedSubjects.put( DependencyManagement.Subject.EXCLUSIONS, - depMngt.isSubjectEnforced(DependencyManagement.Subject.EXCLUSIONS)); + depMngt.isManagedSubjectEnforced(DependencyManagement.Subject.EXCLUSIONS)); } } From 6cf8ed0e94e3a3129d28f367403c1a02ed7793e5 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 7 Oct 2025 11:47:35 +0200 Subject: [PATCH 12/13] Keep proper order in enum --- .../org/eclipse/aether/collection/DependencyManagement.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) 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 3779c02ec..23652eedd 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 @@ -39,8 +39,8 @@ public enum Subject { VERSION, SCOPE, OPTIONAL, - PROPERTIES, - EXCLUSIONS + EXCLUSIONS, + PROPERTIES } private final Map managedValues; From 52f5adb8c93690131486eb332b376b14bbe195c1 Mon Sep 17 00:00:00 2001 From: Tamas Cservenak Date: Tue, 7 Oct 2025 11:56:31 +0200 Subject: [PATCH 13/13] Fix since --- .../aether/internal/impl/collect/PremanagedDependency.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java index d2e3d33ac..f443f51c3 100644 --- a/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java +++ b/maven-resolver-impl/src/main/java/org/eclipse/aether/internal/impl/collect/PremanagedDependency.java @@ -54,7 +54,7 @@ public class PremanagedDependency { final Map premanagedProperties; /** - * @since 2.0.13 + * @since 2.0.14 */ final Map managedSubjects;