Class AbstractDependencyManager

  • All Implemented Interfaces:
    org.eclipse.aether.collection.DependencyManager
    Direct Known Subclasses:
    ClassicDependencyManager, DefaultDependencyManager, TransitiveDependencyManager

    public abstract class AbstractDependencyManager
    extends java.lang.Object
    implements org.eclipse.aether.collection.DependencyManager
    A dependency manager support class for Maven-specific dependency graph management.

    Overview

    This implementation works in conjunction with Maven ModelBuilder to handle dependency management across the dependency graph. While ModelBuilder manages dependencies within a single POM context (inheritance, imports), this class applies lineage-based modifications based on previously recorded dependency management rules sourced from ancestors while building the dependency graph. Root-sourced management rules are special, in that they are always applied, while rules collected during traversal are carefully applied to proper descendants only, to not override work done by ModelBuilder already.

    Managed Properties

    • Version & Scope: Handled by ModelBuilder for own dependency management (think "effective POM"). This implementation ensures these are not applied to the same node that provided the rules, to not override ModelBuilder's work.
    • Optional: Not handled by ModelBuilder; managed here.
    • System Paths: Aligned across the entire graph, ensuring the same system path is used by the same dependency.
    • Exclusions: Always applied as additional information (not effective or applied in the same POM).

    Depth-Based Rule Application

    This implementation achieves proper rule application by tracking "depth" for each collected rule and ignoring rules coming from the same depth as the processed dependency node.

    • Depth 0: Factory instance created during session initialization and parameterized. Collection begins with "derive" operation using root context.
    • Depth 1: Special case for "version", "scope" and "optional" properties. At this level, "apply onto itself" ensures root-defined rules are applied to first-level siblings (which, if managed by ModelBuilder, will be the same, making this a no-op).
    • Depth > 1: "Apply onto itself" is not in effect; only "apply below" is used.

    Rule Precedence

    Rules are keyed by dependency management entry coordinates (GACE: Group, Artifact, Classifier, Extension - see AbstractDependencyManager.Key) and are recorded only if a rule for the same key did not exist previously. This implements the "nearer (to root) management wins" rule, while root management overrides all.

    Managed Bits and Graph Transformations

    When a DependencyNode becomes "managed" by any property provided from this manager, DependencyNode.getManagedBits() 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 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").

    Implementation Notes

    • This class maintains a "path" (list of parent managers) and "depth".
    • The field managedLocalPaths is intentionally left out of hash/equals.
    • Each dependency "derives" an instance with its own context to process second-level dependencies and so on.
    Since:
    2.0.0
    • Method Detail

      • deriveChildManager

        public org.eclipse.aether.collection.DependencyManager deriveChildManager​(org.eclipse.aether.collection.DependencyCollectionContext context)
        Specified by:
        deriveChildManager in interface org.eclipse.aether.collection.DependencyManager
      • manageDependency

        public org.eclipse.aether.collection.DependencyManagement manageDependency​(org.eclipse.aether.graph.Dependency dependency)
        Specified by:
        manageDependency in interface org.eclipse.aether.collection.DependencyManager
      • isDerived

        protected boolean isDerived()
        Returns true if current context should be factored in (collected/derived).
      • isInheritedDerived

        protected boolean isInheritedDerived()
        Manages dependency properties including "version", "scope", "optional", "local path", and "exclusions".

        Property management behavior:

        • Version: Follows 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 isDerived() to maintain compatibility with "classic" behavior (equivalent to deriveUntil=2). For custom transitivity management, override this method or ensure inherited managed properties are handled during graph transformation.

      • isApplied

        protected boolean isApplied()
        Returns true if current dependency should be managed according to so far collected/derived rules.
      • equals

        public boolean equals​(java.lang.Object obj)
        Overrides:
        equals in class java.lang.Object
      • hashCode

        public int hashCode()
        Overrides:
        hashCode in class java.lang.Object