From 2767730c91afe27380991163503212d4ea0e5c28 Mon Sep 17 00:00:00 2001 From: Jan-Jelle Kester Date: Sat, 30 Oct 2021 15:59:26 +0200 Subject: [PATCH 01/15] [MPH-183] [WIP] BOM hierarchy in InputSource --- .../apache/maven/api/model/InputLocation.java | 13 +++ .../maven/api/model/InputLocationTracker.java | 2 + .../apache/maven/api/model/InputSource.java | 16 +++ .../model/building/DefaultModelBuilder.java | 15 ++- .../DefaultDependencyManagementImporter.java | 43 ++++++++ ...faultDependencyManagementImporterTest.java | 104 ++++++++++++++++++ src/mdo/model.vm | 29 ++++- 7 files changed, 216 insertions(+), 6 deletions(-) create mode 100644 maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java index 28bd415366a8..a96a569bae2f 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -32,6 +32,7 @@ public class InputLocation implements Serializable, InputLocationTracker { private final int columnNumber; private final InputSource source; private final Map locations; + private final InputLocation importedFrom = null; public InputLocation(InputSource source) { this.lineNumber = -1; @@ -83,6 +84,13 @@ public Map getLocations() { return locations; } + /** + * Gets the input location that caused this model to be read. + */ + public InputLocation getImportedFrom() { + return importedFrom; + } + /** * Merges the {@code source} location into the {@code target} location. * @@ -169,4 +177,9 @@ public interface StringFormatter { */ String toString(InputLocation location); } + + @Override + public String toString() { + return String.format("%s @ %d:%d", source.getLocation(), lineNumber, columnNumber); + } } diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java index ce4240e053b5..e38ad5c0642a 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java @@ -20,4 +20,6 @@ public interface InputLocationTracker { InputLocation getLocation(Object field); + + InputLocation getImportedFrom(); } diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java index d5dc895fb7a2..60c8566d127e 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java @@ -33,11 +33,19 @@ public class InputSource implements Serializable { private final String modelId; private final String location; private final List inputs; + private final InputLocation importedFrom; public InputSource(String modelId, String location) { this.modelId = modelId; this.location = location; this.inputs = null; + this.importedFrom = null; + } + + private InputSource(String modelId, String location, InputLocation importedFrom) { + this.modelId = modelId; + this.location = location; + this.importedFrom = importedFrom; } public InputSource(Collection inputs) { @@ -64,6 +72,14 @@ public String getModelId() { return this.modelId; } + public InputLocation getImportedFrom() { + return importedFrom; + } + + public InputSource importedFrom(InputLocation importedFrom) { + return new InputSource(modelId, location, importedFrom); + } + @Override public boolean equals(Object o) { if (this == o) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 7d832654a12e..90fbc8cbf998 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1660,14 +1660,14 @@ private void importDependencyManagement( Model model, ModelBuildingRequest request, DefaultModelProblemCollector problems, - Collection importIds) { + Collection importIds) { // a chain of model ID's that caused this depMgt to be loaded?! DependencyManagement depMgmt = model.getDependencyManagement(); if (depMgmt == null) { return; } - String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion(); + String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();// the one that's causing the iport to happen? importIds.add(importing); @@ -1690,7 +1690,16 @@ private void importDependencyManagement( importMgmts = new ArrayList<>(); } - importMgmts.add(importMgmt.getDelegate()); + if (request.isLocationTracking()) { + // Keep track of why this DependencyManagement was imported. + importMgmts.add( + org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) + .importedFrom(dependency.getDelegate().getLocation("")) + .build() + ); + } else { + importMgmts.add(importMgmt.getDelegate()); + } } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index 613e8e160561..507b26c201d4 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -27,6 +27,8 @@ import org.apache.maven.api.model.DependencyManagement; import org.apache.maven.api.model.Exclusion; import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputSource; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblem; import org.apache.maven.model.building.ModelProblemCollector; @@ -73,6 +75,11 @@ public Model importManagement( + toString(present) + ". Add a the conflicting managed dependency directly " + "to the dependencyManagement section of the POM.")); } + + if (request.isLocationTracking()) { + Dependency updatedDependency = updateWithImportedFrom(dependency, source); + dependencies.put(key, updatedDependency); + } } } @@ -136,4 +143,40 @@ private boolean equals(Exclusion e1, Exclusion e2) { return Objects.equals(e1.getGroupId(), e2.getGroupId()) && Objects.equals(e1.getArtifactId(), e2.getArtifactId()); } + + static Dependency updateWithImportedFrom(Dependency dependency, DependencyManagement bom) { + // We are only interested in the InputSource, so the location of the element is sufficient + InputLocation dependencyLocation = dependency.getLocation(""); + InputLocation bomLocation = bom.getLocation(""); + + if (dependencyLocation == null || bomLocation == null) { + return dependency; + } + + InputSource dependencySource = dependencyLocation.getSource(); + InputSource bomSource = bomLocation.getSource(); + + // TODO If the dependency and BOM have the same source, it means we found the root where the dependency is declared. + if (dependencySource == null + || bomSource == null + || Objects.equals(dependencySource.getModelId(), bomSource.getModelId())) { + return Dependency.newBuilder(dependency, true).importedFrom(bomLocation).build(); + } + + while (dependencySource.getImportedFrom() != null) { + InputLocation importedFrom = dependencySource.getImportedFrom(); + + // Stop if the BOM is already in the list, no update necessary + if (Objects.equals(importedFrom.getSource().getModelId(), bomSource.getModelId())) { + return dependency; + } + + dependencySource = importedFrom.getSource(); + } + + // We modify the input location that is used for the whole file. + // This is likely correct because the POM hierarchy applies to the whole POM, not just one dependency. + // TODO What to do now?! + return Dependency.newBuilder(dependency, true).importedFrom(bomLocation).build(); + } } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java new file mode 100644 index 000000000000..2fbb2089f576 --- /dev/null +++ b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java @@ -0,0 +1,104 @@ +/* + * 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.apache.maven.model.composition; + +class DefaultDependencyManagementImporterTest { + // TODO Need to rewrite tests as soon as the SUT is a bit more stable + /* + @Test + public void testUpdateDependencyHierarchy_SameSource() { + InputSource source = new InputSource(); + source.setModelId("SINGLE_SOURCE"); + Dependency dependency = new Dependency(); + dependency.setLocation("", new InputLocation(1, 1, source)); + DependencyManagement bom = new DependencyManagement(); + bom.setLocation("", new InputLocation(2, 2, source)); + + DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); + + assertSame(source, dependency.getLocation("").getSource()); + assertSame(source, bom.getLocation("").getSource()); + assertNull(source.getImportedBy()); + } + + @Test + public void testUpdateDependencyHierarchy_SingleLevel() { + InputSource dependencySource = new InputSource(); + dependencySource.setModelId("DEPENDENCY"); + InputSource bomSource = new InputSource(); + bomSource.setModelId("BOM"); + Dependency dependency = new Dependency(); + dependency.setLocation("", new InputLocation(1, 1, dependencySource)); + DependencyManagement bom = new DependencyManagement(); + bom.setLocation("", new InputLocation(2, 2, bomSource)); + + DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); + + assertSame(dependencySource, dependency.getLocation("").getSource()); + assertSame(bomSource, bom.getLocation("").getSource()); + assertEquals(bomSource, dependencySource.getImportedBy()); + } + + @Test + public void testUpdateDependencyHierarchy_MultiLevel() { + InputSource intermediateSource = new InputSource(); + intermediateSource.setModelId("INTERMEDIATE"); + InputSource dependencySource = new InputSource(); + dependencySource.setModelId("DEPENDENCY"); + dependencySource.setImportedBy(intermediateSource); + InputSource bomSource = new InputSource(); + bomSource.setModelId("BOM"); + Dependency dependency = new Dependency(); + dependency.setLocation("", new InputLocation(1, 1, dependencySource)); + DependencyManagement bom = new DependencyManagement(); + bom.setLocation("", new InputLocation(2, 2, bomSource)); + + DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); + + assertSame(dependencySource, dependency.getLocation("").getSource()); + assertSame(bomSource, bom.getLocation("").getSource()); + assertEquals(intermediateSource, dependencySource.getImportedBy()); + assertEquals(bomSource, intermediateSource.getImportedBy()); + } + + @Test + public void testUpdateDependencyHierarchy_PresentSource() { + InputSource bomSource = new InputSource(); + bomSource.setModelId("BOM"); + InputSource intermediateSource = new InputSource(); + intermediateSource.setModelId("INTERMEDIATE"); + intermediateSource.setImportedBy(bomSource); + InputSource dependencySource = new InputSource(); + dependencySource.setModelId("DEPENDENCY"); + dependencySource.setImportedBy(intermediateSource); + Dependency dependency = new Dependency(); + dependency.setLocation("", new InputLocation(1, 1, dependencySource)); + DependencyManagement bom = new DependencyManagement(); + bom.setLocation("", new InputLocation(2, 2, bomSource)); + + DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); + + assertSame(dependencySource, dependency.getLocation("").getSource()); + assertSame(bomSource, bom.getLocation("").getSource()); + assertEquals(intermediateSource, dependencySource.getImportedBy()); + assertEquals(bomSource, intermediateSource.getImportedBy()); + assertNull(bomSource.getImportedBy()); + } + */ +} diff --git a/src/mdo/model.vm b/src/mdo/model.vm index be741434ac5e..61dc00f6aacc 100644 --- a/src/mdo/model.vm +++ b/src/mdo/model.vm @@ -138,6 +138,8 @@ public class ${class.name} #if ( ! $class.superClass ) /** Locations */ final Map locations; + /** Location tracking */ + final InputLocation importedFrom; #end #end @@ -159,7 +161,8 @@ public class ${class.name} $type $field.name${sep} #end #if ( $locationTracking ) - Map locations + Map locations, + InputLocation importedFrom #end ) { #if ( $class.superClass ) @@ -169,7 +172,8 @@ public class ${class.name} ${field.name}${sep} #end #if ( $locationTracking ) - locations + locations, + importedFrom #end ); #end @@ -187,6 +191,7 @@ public class ${class.name} #if ( $locationTracking ) #if ( ! $class.superClass ) this.locations = ImmutableCollections.copy(locations); + this.importedFrom = importedFrom; #end #end } @@ -252,6 +257,14 @@ public class ${class.name} return locations != null ? locations.get(key) : null; } + /** + * Gets the input location that caused this model to be read. + */ + public InputLocation getImportedFrom() + { + return importedFrom; + } + #end /** * Creates a new builder with this object as the basis. @@ -382,6 +395,7 @@ public class ${class.name} #end #if ( ! $class.superClass && $locationTracking ) Map locations; + InputLocation importedFrom; #end Builder(boolean withDefaults) { @@ -416,6 +430,7 @@ public class ${class.name} #end #if ( $locationTracking ) this.locations = base.locations; + this.importedFrom = base.importedFrom; #end } else { this.base = base; @@ -461,6 +476,13 @@ public class ${class.name} return this; } + @Nonnull + public Builder importedFrom( InputLocation importedFrom ) + { + this.importedFrom = importedFrom; + return this; + } + #end @Nonnull public ${class.name} build() { @@ -494,7 +516,8 @@ public class ${class.name} #end #end #if ( $locationTracking ) - locations + locations, + importedFrom #end ); } From 550bb4dd8bd1e63410d1446106252295fe1f9744 Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Thu, 13 Apr 2023 15:07:47 +0200 Subject: [PATCH 02/15] Formatting --- .../apache/maven/model/building/DefaultModelBuilder.java | 7 +++---- .../composition/DefaultDependencyManagementImporter.java | 4 +++- 2 files changed, 6 insertions(+), 5 deletions(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 90fbc8cbf998..7249c8a28d70 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1693,10 +1693,9 @@ private void importDependencyManagement( if (request.isLocationTracking()) { // Keep track of why this DependencyManagement was imported. importMgmts.add( - org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) - .importedFrom(dependency.getDelegate().getLocation("")) - .build() - ); + org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) + .importedFrom(dependency.getDelegate().getLocation("")) + .build()); } else { importMgmts.add(importMgmt.getDelegate()); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index 507b26c201d4..90760a4d4958 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -160,7 +160,9 @@ static Dependency updateWithImportedFrom(Dependency dependency, DependencyManage if (dependencySource == null || bomSource == null || Objects.equals(dependencySource.getModelId(), bomSource.getModelId())) { - return Dependency.newBuilder(dependency, true).importedFrom(bomLocation).build(); + return Dependency.newBuilder(dependency, true) + .importedFrom(bomLocation) + .build(); } while (dependencySource.getImportedFrom() != null) { From 198c58119ca8ce4fd43e83d9716a11f7a7f13e4a Mon Sep 17 00:00:00 2001 From: Maarten Mulders Date: Wed, 10 May 2023 14:27:08 +0200 Subject: [PATCH 03/15] WIP and notes --- .../src/main/java/org/apache/maven/api/model/InputSource.java | 2 ++ .../org/apache/maven/model/building/DefaultModelBuilder.java | 3 ++- .../composition/DefaultDependencyManagementImporter.java | 4 ++-- 3 files changed, 6 insertions(+), 3 deletions(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java index 60c8566d127e..003d013a8db1 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java @@ -45,6 +45,7 @@ public InputSource(String modelId, String location) { private InputSource(String modelId, String location, InputLocation importedFrom) { this.modelId = modelId; this.location = location; + this.inputs = null; this.importedFrom = importedFrom; } @@ -52,6 +53,7 @@ public InputSource(Collection inputs) { this.modelId = null; this.location = null; this.inputs = ImmutableCollections.copy(inputs); + this.importedFrom = null; } /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 7249c8a28d70..06fd3ddef2fc 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1667,7 +1667,8 @@ private void importDependencyManagement( return; } - String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion();// the one that's causing the iport to happen? + // the one that's causing the import to happen? + String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion(); importIds.add(importing); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index 90760a4d4958..2a91073c3309 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -26,9 +26,9 @@ import org.apache.maven.api.model.Dependency; import org.apache.maven.api.model.DependencyManagement; import org.apache.maven.api.model.Exclusion; -import org.apache.maven.api.model.Model; import org.apache.maven.api.model.InputLocation; import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblem; import org.apache.maven.model.building.ModelProblemCollector; @@ -156,7 +156,7 @@ static Dependency updateWithImportedFrom(Dependency dependency, DependencyManage InputSource dependencySource = dependencyLocation.getSource(); InputSource bomSource = bomLocation.getSource(); - // TODO If the dependency and BOM have the same source, it means we found the root where the dependency is declared. + // If the dependency and BOM have the same source, it means we found the root where the dependency is declared. if (dependencySource == null || bomSource == null || Objects.equals(dependencySource.getModelId(), bomSource.getModelId())) { From 38dc0349d99776a29b904c73d46c8d607a81d448 Mon Sep 17 00:00:00 2001 From: Juul Hobert Date: Fri, 9 Feb 2024 15:43:18 +0100 Subject: [PATCH 04/15] [MNG-7344] Recursive imported from tracking --- .../org/apache/maven/api/model/InputLocation.java | 13 ++++++++++++- .../DefaultDependencyManagementImporter.java | 6 ++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java index a96a569bae2f..dc81d2da83a4 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -32,13 +32,14 @@ public class InputLocation implements Serializable, InputLocationTracker { private final int columnNumber; private final InputSource source; private final Map locations; - private final InputLocation importedFrom = null; + private final InputLocation importedFrom; public InputLocation(InputSource source) { this.lineNumber = -1; this.columnNumber = -1; this.source = source; this.locations = Collections.singletonMap(0, this); + this.importedFrom = null; } public InputLocation(int lineNumber, int columnNumber) { @@ -55,6 +56,7 @@ public InputLocation(int lineNumber, int columnNumber, InputSource source, Objec this.source = source; this.locations = selfLocationKey != null ? Collections.singletonMap(selfLocationKey, this) : Collections.emptyMap(); + this.importedFrom = null; } public InputLocation(int lineNumber, int columnNumber, InputSource source, Map locations) { @@ -62,6 +64,15 @@ public InputLocation(int lineNumber, int columnNumber, InputSource source, Map Date: Fri, 1 Mar 2024 16:25:17 +0100 Subject: [PATCH 05/15] [MNG-7344] Imported from in the v3 model --- .../model/building/DefaultModelBuilder.java | 6 +++-- .../org/apache/maven/model/InputLocation.java | 24 +++++++++++++++++ .../org/apache/maven/model/InputSource.java | 27 +++++++++++++++++++ src/mdo/model-v3.vm | 10 +++++++ 4 files changed, 65 insertions(+), 2 deletions(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 06fd3ddef2fc..2bbc6ec264fc 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1705,8 +1705,10 @@ private void importDependencyManagement( importIds.remove(importing); - model.update( - dependencyManagementImporter.importManagement(model.getDelegate(), importMgmts, request, problems)); + org.apache.maven.api.model.Model updatedModel = + dependencyManagementImporter.importManagement(model.getDelegate(), importMgmts, request, problems); + model.update(updatedModel); + model.setDependencyManagement(new DependencyManagement(updatedModel.getDependencyManagement())); } private DependencyManagement loadDependencyManagement( diff --git a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java index 1b48e0463e49..b9bcac7f5f22 100644 --- a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java +++ b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java @@ -59,6 +59,11 @@ public final class InputLocation implements java.io.Serializable, Cloneable, Inp */ private InputLocation location; + /** + * Field importedFrom. + */ + private InputLocation importedFrom; + // ----------------/ // - Constructors -/ // ----------------/ @@ -73,6 +78,7 @@ public InputLocation(org.apache.maven.api.model.InputLocation location) { .collect(Collectors.toMap( e -> e.getKey(), e -> e.getValue() == location ? this : new InputLocation(e.getValue()))); + this.importedFrom = location.getImportedFrom() != null ? new InputLocation(location.getImportedFrom()) : null; } public InputLocation(int lineNumber, int columnNumber) { @@ -217,6 +223,24 @@ public InputSource getSource() { return this.source; } // -- InputSource getSource() + /** + * Get the imported from location. + * + * @return InputLocation + */ + public InputLocation getImportedFrom() { + return importedFrom; + } + + /** + * Set the imported from location. + * + * @param importedFrom + */ + public void setImportedFrom(InputLocation importedFrom) { + this.importedFrom = importedFrom; + } + /** * Method merge. * diff --git a/maven-model/src/main/java/org/apache/maven/model/InputSource.java b/maven-model/src/main/java/org/apache/maven/model/InputSource.java index 10674ecc1ad2..1bd81e925ee0 100644 --- a/maven-model/src/main/java/org/apache/maven/model/InputSource.java +++ b/maven-model/src/main/java/org/apache/maven/model/InputSource.java @@ -50,6 +50,14 @@ public class InputSource implements java.io.Serializable, Cloneable { */ private String location; + /** + * + * + * The location of the POM from which this POM was + * imported from or {@code null} if unknown. + */ + private InputLocation importedFrom; + // ----------------/ // - Constructors -/ // ----------------/ @@ -59,6 +67,7 @@ public InputSource() {} public InputSource(org.apache.maven.api.model.InputSource source) { this.modelId = source.getModelId(); this.location = source.getLocation(); + this.importedFrom = source.getImportedFrom() != null ? new InputLocation(source.getImportedFrom()) : null; } // -----------/ @@ -119,6 +128,24 @@ public void setModelId(String modelId) { this.modelId = modelId; } // -- void setModelId( String ) + /** + * Get the location of the POM from which this POM was + * + * @return + */ + public InputLocation getImportedFrom() { + return importedFrom; + } + + /** + * Set the location of the POM from which this POM was imported from. + * + * @param importedFrom + */ + public void setImportedFrom(InputLocation importedFrom) { + this.importedFrom = importedFrom; + } + @Override public String toString() { return getModelId() + " " + getLocation(); diff --git a/src/mdo/model-v3.vm b/src/mdo/model-v3.vm index f399783ba875..0f04506cfe69 100644 --- a/src/mdo/model-v3.vm +++ b/src/mdo/model-v3.vm @@ -282,6 +282,16 @@ public class ${class.name} .location(key, location.toApiLocation()).build()); } + public InputLocation getImportedFrom() { + ${packageModelV4}.InputLocation loc = getDelegate().getImportedFrom(); + return loc != null ? new InputLocation(loc) : null; + } + + public void setImportedFrom(InputLocation location) { + update(${packageModelV4}.${class.name}.newBuilder(getDelegate(), true) + .importedFrom(location.toApiLocation()).build()); + } + #end protected boolean replace(Object oldDelegate, Object newDelegate) { if (super.replace(oldDelegate, newDelegate)) { From 3cd4d9d69d6c91cfa3c8c24d4d0454867815c4fb Mon Sep 17 00:00:00 2001 From: Giovanni van der Schelde Date: Fri, 15 Mar 2024 10:52:33 +0100 Subject: [PATCH 06/15] [MPH-183] Fix error in import path and small refactor --- .../org/apache/maven/api/model/InputLocation.java | 4 ++-- .../maven/model/building/DefaultModelBuilder.java | 12 ++++++------ .../DefaultDependencyManagementImporter.java | 3 +-- 3 files changed, 9 insertions(+), 10 deletions(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java index dc81d2da83a4..9ec46decaa13 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -67,12 +67,12 @@ public InputLocation(int lineNumber, int columnNumber, InputSource source, Map importIds) { // a chain of model ID's that caused this depMgt to be loaded?! + Collection importIds) { DependencyManagement depMgmt = model.getDependencyManagement(); if (depMgmt == null) { return; } - // the one that's causing the import to happen? String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion(); importIds.add(importing); + // Model v4 List importMgmts = null; for (Iterator it = depMgmt.getDependencies().iterator(); it.hasNext(); ) { @@ -1684,6 +1684,7 @@ private void importDependencyManagement( it.remove(); + // Model v3 DependencyManagement importMgmt = loadDependencyManagement(model, request, problems, dependency, importIds); if (importMgmt != null) { @@ -1693,6 +1694,7 @@ private void importDependencyManagement( if (request.isLocationTracking()) { // Keep track of why this DependencyManagement was imported. + // And map model v3 to model v4 -> importMgmt(v3).getDelegate() returns a v4 object importMgmts.add( org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) .importedFrom(dependency.getDelegate().getLocation("")) @@ -1705,10 +1707,8 @@ private void importDependencyManagement( importIds.remove(importing); - org.apache.maven.api.model.Model updatedModel = - dependencyManagementImporter.importManagement(model.getDelegate(), importMgmts, request, problems); - model.update(updatedModel); - model.setDependencyManagement(new DependencyManagement(updatedModel.getDependencyManagement())); + model.update( + dependencyManagementImporter.importManagement(model.getDelegate(), importMgmts, request, problems)); } private DependencyManagement loadDependencyManagement( diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index c560cfed1bce..9ba634adfebf 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -178,9 +178,8 @@ static Dependency updateWithImportedFrom(Dependency dependency, DependencyManage // We modify the input location that is used for the whole file. // This is likely correct because the POM hierarchy applies to the whole POM, not just one dependency. - // TODO What to do now?! return Dependency.newBuilder(dependency, true) - .importedFrom(new InputLocation(bomLocation, dependency.getImportedFrom())) + .importedFrom(new InputLocation(bomLocation)) .build(); } } From b50cda266ad455011869ee32d59daf642b000938 Mon Sep 17 00:00:00 2001 From: Giovanni van der Schelde Date: Fri, 15 Mar 2024 14:19:08 +0100 Subject: [PATCH 07/15] [MPH-183] Remove indentation for readability --- .../model/building/DefaultModelBuilder.java | 29 +++++++++---------- 1 file changed, 13 insertions(+), 16 deletions(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 1b5700054d92..5816408979bd 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1672,7 +1672,7 @@ private void importDependencyManagement( importIds.add(importing); // Model v4 - List importMgmts = null; + List importMgmts = new ArrayList<>(); for (Iterator it = depMgmt.getDependencies().iterator(); it.hasNext(); ) { Dependency dependency = it.next(); @@ -1686,22 +1686,19 @@ private void importDependencyManagement( // Model v3 DependencyManagement importMgmt = loadDependencyManagement(model, request, problems, dependency, importIds); + if (importMgmt == null) { + continue; + } - if (importMgmt != null) { - if (importMgmts == null) { - importMgmts = new ArrayList<>(); - } - - if (request.isLocationTracking()) { - // Keep track of why this DependencyManagement was imported. - // And map model v3 to model v4 -> importMgmt(v3).getDelegate() returns a v4 object - importMgmts.add( - org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) - .importedFrom(dependency.getDelegate().getLocation("")) - .build()); - } else { - importMgmts.add(importMgmt.getDelegate()); - } + if (request.isLocationTracking()) { + // Keep track of why this DependencyManagement was imported. + // And map model v3 to model v4 -> importMgmt(v3).getDelegate() returns a v4 object + importMgmts.add( + org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) + .importedFrom(dependency.getDelegate().getLocation("")) + .build()); + } else { + importMgmts.add(importMgmt.getDelegate()); } } From 9881c2226542a9bdd7dfc1101e7224a0241a2b66 Mon Sep 17 00:00:00 2001 From: Giovanni van der Schelde Date: Fri, 15 Mar 2024 15:21:36 +0100 Subject: [PATCH 08/15] [MPH-183] Add getLocationKeys for help plugin --- src/mdo/model-v3.vm | 5 +++++ src/mdo/model.vm | 8 ++++++++ 2 files changed, 13 insertions(+) diff --git a/src/mdo/model-v3.vm b/src/mdo/model-v3.vm index 0f04506cfe69..168d352d2c11 100644 --- a/src/mdo/model-v3.vm +++ b/src/mdo/model-v3.vm @@ -52,6 +52,7 @@ #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.List" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "java.util.Set" ) ) #set ( $dummy = $imports.add( "java.util.Objects" ) ) #set ( $dummy = $imports.add( "java.util.stream.Collectors" ) ) #set ( $dummy = $imports.add( "java.util.stream.Stream" ) ) @@ -292,6 +293,10 @@ public class ${class.name} .importedFrom(location.toApiLocation()).build()); } + public Set getLocationKeys() { + return getDelegate().getLocationKeys(); + } + #end protected boolean replace(Object oldDelegate, Object newDelegate) { if (super.replace(oldDelegate, newDelegate)) { diff --git a/src/mdo/model.vm b/src/mdo/model.vm index 61dc00f6aacc..f53ebd8ee06d 100644 --- a/src/mdo/model.vm +++ b/src/mdo/model.vm @@ -49,6 +49,7 @@ #set ( $dummy = $imports.add( "java.util.Collections" ) ) #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "java.util.Set" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Experimental" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) @@ -257,6 +258,13 @@ public class ${class.name} return locations != null ? locations.get(key) : null; } + /** + * Gets the keys of the locations of the input source. + */ + public Set getLocationKeys() { + return locations != null ? locations.keySet() : null; + } + /** * Gets the input location that caused this model to be read. */ From 941b50273914ef531472b6856358b4c8629e9081 Mon Sep 17 00:00:00 2001 From: Juul Hobert Date: Fri, 29 Mar 2024 10:01:11 +0100 Subject: [PATCH 09/15] [MNG-7344] Unit tests for updatedWithImportedFrom --- ...faultDependencyManagementImporterTest.java | 161 ++++++++++-------- 1 file changed, 90 insertions(+), 71 deletions(-) diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java index 2fbb2089f576..fdf39ab4b17f 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java @@ -18,87 +18,106 @@ */ package org.apache.maven.model.composition; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputSource; +import org.junit.jupiter.api.Test; + +import static org.assertj.core.api.Assertions.assertThat; + class DefaultDependencyManagementImporterTest { - // TODO Need to rewrite tests as soon as the SUT is a bit more stable - /* @Test - public void testUpdateDependencyHierarchy_SameSource() { - InputSource source = new InputSource(); - source.setModelId("SINGLE_SOURCE"); - Dependency dependency = new Dependency(); - dependency.setLocation("", new InputLocation(1, 1, source)); - DependencyManagement bom = new DependencyManagement(); - bom.setLocation("", new InputLocation(2, 2, source)); - - DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); - - assertSame(source, dependency.getLocation("").getSource()); - assertSame(source, bom.getLocation("").getSource()); - assertNull(source.getImportedBy()); + void testUpdateWithImportedFrom_dependencyLocationAndBomLocationAreNull_dependencyReturned() { + final Dependency dependency = Dependency.newBuilder().build(); + final DependencyManagement depMgmt = DependencyManagement.newBuilder().build(); + final Dependency result = DefaultDependencyManagementImporter.updateWithImportedFrom(dependency, depMgmt); + + assertThat(dependency).isEqualTo(result); + } + + @Test + void testUpdateWithImportedFrom_bomAndDependencyHaveSameSource_dependencyRootFound() { + final InputSource source = new InputSource("SINGLE_SOURCE", ""); + final Dependency dependency = Dependency.newBuilder() + .location("", new InputLocation(1, 1, source)) + .build(); + final DependencyManagement bom = DependencyManagement.newBuilder() + .location("", new InputLocation(1, 1, source)) + .build(); + + final Dependency result = DefaultDependencyManagementImporter.updateWithImportedFrom(dependency, bom); + + assertThat(result).isNotNull(); + assertThat(result.getImportedFrom()).isEqualTo(bom.getLocation("")); } @Test - public void testUpdateDependencyHierarchy_SingleLevel() { - InputSource dependencySource = new InputSource(); - dependencySource.setModelId("DEPENDENCY"); - InputSource bomSource = new InputSource(); - bomSource.setModelId("BOM"); - Dependency dependency = new Dependency(); - dependency.setLocation("", new InputLocation(1, 1, dependencySource)); - DependencyManagement bom = new DependencyManagement(); - bom.setLocation("", new InputLocation(2, 2, bomSource)); - - DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); - - assertSame(dependencySource, dependency.getLocation("").getSource()); - assertSame(bomSource, bom.getLocation("").getSource()); - assertEquals(bomSource, dependencySource.getImportedBy()); + public void testUpdateWithImportedFrom_singleLevel_importedFromSet() { + // Arrange + final InputSource dependencySource = new InputSource("DEPENDENCY", "DEPENDENCY"); + final InputSource bomSource = new InputSource("BOM", "BOM"); + final Dependency dependency = Dependency.newBuilder() + .location("", new InputLocation(1, 1, dependencySource)) + .build(); + final DependencyManagement bom = DependencyManagement.newBuilder() + .location("", new InputLocation(2, 2, bomSource)) + .build(); + + // Act + final Dependency result = DefaultDependencyManagementImporter.updateWithImportedFrom(dependency, bom); + + // Assert + assertThat(result).isNotNull(); + assertThat(result.getImportedFrom().toString()) + .isEqualTo(bom.getLocation("").toString()); } @Test - public void testUpdateDependencyHierarchy_MultiLevel() { - InputSource intermediateSource = new InputSource(); - intermediateSource.setModelId("INTERMEDIATE"); - InputSource dependencySource = new InputSource(); - dependencySource.setModelId("DEPENDENCY"); - dependencySource.setImportedBy(intermediateSource); - InputSource bomSource = new InputSource(); - bomSource.setModelId("BOM"); - Dependency dependency = new Dependency(); - dependency.setLocation("", new InputLocation(1, 1, dependencySource)); - DependencyManagement bom = new DependencyManagement(); - bom.setLocation("", new InputLocation(2, 2, bomSource)); - - DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); - - assertSame(dependencySource, dependency.getLocation("").getSource()); - assertSame(bomSource, bom.getLocation("").getSource()); - assertEquals(intermediateSource, dependencySource.getImportedBy()); - assertEquals(bomSource, intermediateSource.getImportedBy()); + public void testUpdateWithImportedFrom_multiLevel_importedFromSetChanged() { + // Arrange + final InputSource bomSource = new InputSource("BOM", "BOM"); + final InputSource intermediateSource = + new InputSource("INTERMEDIATE", "INTERMEDIATE").importedFrom(new InputLocation(bomSource)); + final InputSource dependencySource = + new InputSource("DEPENDENCY", "DEPENDENCY").importedFrom(new InputLocation(intermediateSource)); + final InputLocation bomLocation = new InputLocation(2, 2, bomSource); + final Dependency dependency = Dependency.newBuilder() + .location("", new InputLocation(1, 1, dependencySource)) + .importedFrom(bomLocation) + .build(); + final DependencyManagement bom = + DependencyManagement.newBuilder().location("", bomLocation).build(); + + // Act + final Dependency result = DefaultDependencyManagementImporter.updateWithImportedFrom(dependency, bom); + + // Assert + assertThat(result.getImportedFrom().toString()) + .isEqualTo(bom.getLocation("").toString()); } @Test - public void testUpdateDependencyHierarchy_PresentSource() { - InputSource bomSource = new InputSource(); - bomSource.setModelId("BOM"); - InputSource intermediateSource = new InputSource(); - intermediateSource.setModelId("INTERMEDIATE"); - intermediateSource.setImportedBy(bomSource); - InputSource dependencySource = new InputSource(); - dependencySource.setModelId("DEPENDENCY"); - dependencySource.setImportedBy(intermediateSource); - Dependency dependency = new Dependency(); - dependency.setLocation("", new InputLocation(1, 1, dependencySource)); - DependencyManagement bom = new DependencyManagement(); - bom.setLocation("", new InputLocation(2, 2, bomSource)); - - DefaultDependencyManagementImporter.updateDependencyImports(dependency, bom); - - assertSame(dependencySource, dependency.getLocation("").getSource()); - assertSame(bomSource, bom.getLocation("").getSource()); - assertEquals(intermediateSource, dependencySource.getImportedBy()); - assertEquals(bomSource, intermediateSource.getImportedBy()); - assertNull(bomSource.getImportedBy()); + public void testUpdateWithImportedFrom_multiLevelAlreadyFoundInDifferentSource_importedFromSetMaintained() { + // Arrange + final InputSource bomSource = new InputSource("BOM", "BOM"); + final InputSource intermediateSource = + new InputSource("INTERMEDIATE", "INTERMEDIATE").importedFrom(new InputLocation(bomSource)); + final InputSource dependencySource = + new InputSource("DEPENDENCY", "DEPENDENCY").importedFrom(new InputLocation(intermediateSource)); + final Dependency dependency = Dependency.newBuilder() + .location("", new InputLocation(1, 1, dependencySource)) + .build(); + final DependencyManagement differentSource = DependencyManagement.newBuilder() + .location("", new InputLocation(2, 2, new InputSource("BOM2", "BOM2"))) + .build(); + + // Act + final Dependency result = + DefaultDependencyManagementImporter.updateWithImportedFrom(dependency, differentSource); + + // Assert + assertThat(result.getImportedFrom().toString()) + .isEqualTo(differentSource.getLocation("").toString()); } - */ } From 71c29891bf6f731cf85ef34d3fde6b281ebbcb32 Mon Sep 17 00:00:00 2001 From: Giovanni van der Schelde Date: Fri, 29 Mar 2024 10:44:11 +0100 Subject: [PATCH 10/15] [MPH-183] Rename test to better match behaviour --- .../composition/DefaultDependencyManagementImporterTest.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java index fdf39ab4b17f..5e035541be41 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java @@ -37,7 +37,7 @@ void testUpdateWithImportedFrom_dependencyLocationAndBomLocationAreNull_dependen } @Test - void testUpdateWithImportedFrom_bomAndDependencyHaveSameSource_dependencyRootFound() { + void testUpdateWithImportedFrom_dependencyManagementAndDependencyHaveSameSource_dependencyImportedFromSameSource() { final InputSource source = new InputSource("SINGLE_SOURCE", ""); final Dependency dependency = Dependency.newBuilder() .location("", new InputLocation(1, 1, source)) @@ -49,7 +49,8 @@ void testUpdateWithImportedFrom_bomAndDependencyHaveSameSource_dependencyRootFou final Dependency result = DefaultDependencyManagementImporter.updateWithImportedFrom(dependency, bom); assertThat(result).isNotNull(); - assertThat(result.getImportedFrom()).isEqualTo(bom.getLocation("")); + assertThat(result.getImportedFrom().toString()) + .isEqualTo(bom.getLocation("").toString()); } @Test From 21541edd6b6d33b5e2552c540ed10338d25042bb Mon Sep 17 00:00:00 2001 From: Juul Hobert Date: Fri, 12 Apr 2024 10:29:51 +0200 Subject: [PATCH 11/15] [MNG-7344] Removed line that changed the importedFrom in the dep mgmt where it shouldn't --- .../org/apache/maven/model/building/DefaultModelBuilder.java | 1 - 1 file changed, 1 deletion(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 5816408979bd..26d1089e9bad 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1695,7 +1695,6 @@ private void importDependencyManagement( // And map model v3 to model v4 -> importMgmt(v3).getDelegate() returns a v4 object importMgmts.add( org.apache.maven.api.model.DependencyManagement.newBuilder(importMgmt.getDelegate(), true) - .importedFrom(dependency.getDelegate().getLocation("")) .build()); } else { importMgmts.add(importMgmt.getDelegate()); From 1a9aa520b9372848c45387d71cf0231f703544ab Mon Sep 17 00:00:00 2001 From: Giovanni van der Schelde Date: Fri, 12 Apr 2024 10:37:05 +0200 Subject: [PATCH 12/15] [MNG-7344] Improve comment on getImportedFrom method --- .../main/java/org/apache/maven/api/model/InputLocation.java | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java index 9ec46decaa13..bfe302f7bb2d 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -96,7 +96,9 @@ public Map getLocations() { } /** - * Gets the input location that caused this model to be read. + * Gets the parent InputLocation where this InputLocation may have been imported from. + * Can return {@code null}. + * @since 4.0.0 */ public InputLocation getImportedFrom() { return importedFrom; From 237de750f43166cc46b6f06643d8856d102f223c Mon Sep 17 00:00:00 2001 From: Giovanni van der Schelde Date: Fri, 12 Apr 2024 10:42:46 +0200 Subject: [PATCH 13/15] [MNG-7344] Remove unused method and make constructor public --- .../java/org/apache/maven/api/model/InputSource.java | 11 ++--------- .../DefaultDependencyManagementImporterTest.java | 8 ++++---- 2 files changed, 6 insertions(+), 13 deletions(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java index 003d013a8db1..268aa9e47e71 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java @@ -36,13 +36,10 @@ public class InputSource implements Serializable { private final InputLocation importedFrom; public InputSource(String modelId, String location) { - this.modelId = modelId; - this.location = location; - this.inputs = null; - this.importedFrom = null; + this(modelId, location, null); } - private InputSource(String modelId, String location, InputLocation importedFrom) { + public InputSource(String modelId, String location, InputLocation importedFrom) { this.modelId = modelId; this.location = location; this.inputs = null; @@ -78,10 +75,6 @@ public InputLocation getImportedFrom() { return importedFrom; } - public InputSource importedFrom(InputLocation importedFrom) { - return new InputSource(modelId, location, importedFrom); - } - @Override public boolean equals(Object o) { if (this == o) { diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java index 5e035541be41..ee656befbf49 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java @@ -79,9 +79,9 @@ public void testUpdateWithImportedFrom_multiLevel_importedFromSetChanged() { // Arrange final InputSource bomSource = new InputSource("BOM", "BOM"); final InputSource intermediateSource = - new InputSource("INTERMEDIATE", "INTERMEDIATE").importedFrom(new InputLocation(bomSource)); + new InputSource("INTERMEDIATE", "INTERMEDIATE", new InputLocation(bomSource)); final InputSource dependencySource = - new InputSource("DEPENDENCY", "DEPENDENCY").importedFrom(new InputLocation(intermediateSource)); + new InputSource("DEPENDENCY", "DEPENDENCY", new InputLocation(intermediateSource)); final InputLocation bomLocation = new InputLocation(2, 2, bomSource); final Dependency dependency = Dependency.newBuilder() .location("", new InputLocation(1, 1, dependencySource)) @@ -103,9 +103,9 @@ public void testUpdateWithImportedFrom_multiLevelAlreadyFoundInDifferentSource_i // Arrange final InputSource bomSource = new InputSource("BOM", "BOM"); final InputSource intermediateSource = - new InputSource("INTERMEDIATE", "INTERMEDIATE").importedFrom(new InputLocation(bomSource)); + new InputSource("INTERMEDIATE", "INTERMEDIATE", new InputLocation(bomSource)); final InputSource dependencySource = - new InputSource("DEPENDENCY", "DEPENDENCY").importedFrom(new InputLocation(intermediateSource)); + new InputSource("DEPENDENCY", "DEPENDENCY", new InputLocation(intermediateSource)); final Dependency dependency = Dependency.newBuilder() .location("", new InputLocation(1, 1, dependencySource)) .build(); From 73f5ff22bc3b16591c56275af762a661ccefeaa9 Mon Sep 17 00:00:00 2001 From: Giovanni van der Schelde Date: Fri, 12 Apr 2024 10:53:37 +0200 Subject: [PATCH 14/15] [MNG-7344] Add since and docs to methods --- .../java/org/apache/maven/api/model/InputLocation.java | 2 ++ .../org/apache/maven/api/model/InputLocationTracker.java | 7 +++++++ .../main/java/org/apache/maven/api/model/InputSource.java | 7 +++++++ .../main/java/org/apache/maven/model/InputLocation.java | 4 +++- 4 files changed, 19 insertions(+), 1 deletion(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java index bfe302f7bb2d..b72fe65614ea 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -98,6 +98,8 @@ public Map getLocations() { /** * Gets the parent InputLocation where this InputLocation may have been imported from. * Can return {@code null}. + * + * @return InputLocation * @since 4.0.0 */ public InputLocation getImportedFrom() { diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java index e38ad5c0642a..8b2958a35cc6 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java @@ -21,5 +21,12 @@ public interface InputLocationTracker { InputLocation getLocation(Object field); + /** + * Gets the parent InputLocation where this InputLocation may have been imported from. + * Can return {@code null}. + * + * @return InputLocation + * @since 4.0.0 + */ InputLocation getImportedFrom(); } diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java index 268aa9e47e71..1d1998c6b492 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java @@ -71,6 +71,13 @@ public String getModelId() { return this.modelId; } + /** + * Gets the parent InputLocation where this InputLocation may have been imported from. + * Can return {@code null}. + * + * @return InputLocation + * @since 4.0.0 + */ public InputLocation getImportedFrom() { return importedFrom; } diff --git a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java index b9bcac7f5f22..e3fc5fc24c33 100644 --- a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java +++ b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java @@ -224,9 +224,11 @@ public InputSource getSource() { } // -- InputSource getSource() /** - * Get the imported from location. + * Gets the parent InputLocation where this InputLocation may have been imported from. + * Can return {@code null}. * * @return InputLocation + * @since 4.0.0 */ public InputLocation getImportedFrom() { return importedFrom; From 78b912c52f1b0d34d52e438b0d1fc24de955c6ee Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 9 Jul 2024 16:17:43 +0200 Subject: [PATCH 15/15] Move code to new implementation --- maven-api-impl/pom.xml | 4 ++ .../DefaultDependencyManagementImporter.java | 45 ++++++++++++++++++ ...faultDependencyManagementImporterTest.java | 2 +- .../DefaultDependencyManagementImporter.java | 46 ------------------- pom.xml | 6 +++ src/mdo/model.vm | 3 +- 6 files changed, 57 insertions(+), 49 deletions(-) rename {maven-model-builder/src/test/java/org/apache/maven/model/composition => maven-api-impl/src/test/java/org/apache/maven/internal/impl/model}/DefaultDependencyManagementImporterTest.java (99%) diff --git a/maven-api-impl/pom.xml b/maven-api-impl/pom.xml index 44bb10f6cc4a..e0a0968cfd8e 100644 --- a/maven-api-impl/pom.xml +++ b/maven-api-impl/pom.xml @@ -123,6 +123,10 @@ under the License. hamcrest test + + org.assertj + assertj-core + org.apache.maven maven-di diff --git a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultDependencyManagementImporter.java b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultDependencyManagementImporter.java index 25258ff1b201..89d6605670c3 100644 --- a/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultDependencyManagementImporter.java +++ b/maven-api-impl/src/main/java/org/apache/maven/internal/impl/model/DefaultDependencyManagementImporter.java @@ -32,6 +32,8 @@ import org.apache.maven.api.model.Dependency; import org.apache.maven.api.model.DependencyManagement; import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputSource; import org.apache.maven.api.model.Model; import org.apache.maven.api.services.BuilderProblem.Severity; import org.apache.maven.api.services.ModelBuilderRequest; @@ -81,6 +83,10 @@ public Model importManagement( + toString(present) + ". Add the conflicting managed dependency directly " + "to the dependencyManagement section of the POM."); } + if (present == null && request.isLocationTracking()) { + Dependency updatedDependency = updateWithImportedFrom(dependency, source); + dependencies.put(key, updatedDependency); + } } } @@ -144,4 +150,43 @@ private boolean equals(Exclusion e1, Exclusion e2) { return Objects.equals(e1.getGroupId(), e2.getGroupId()) && Objects.equals(e1.getArtifactId(), e2.getArtifactId()); } + + static Dependency updateWithImportedFrom(Dependency dependency, DependencyManagement bom) { + // We are only interested in the InputSource, so the location of the element is sufficient + InputLocation dependencyLocation = dependency.getLocation(""); + InputLocation bomLocation = bom.getLocation(""); + + if (dependencyLocation == null || bomLocation == null) { + return dependency; + } + + InputSource dependencySource = dependencyLocation.getSource(); + InputSource bomSource = bomLocation.getSource(); + + // If the dependency and BOM have the same source, it means we found the root where the dependency is declared. + if (dependencySource == null + || bomSource == null + || Objects.equals(dependencySource.getModelId(), bomSource.getModelId())) { + return Dependency.newBuilder(dependency, true) + .importedFrom(bomLocation) + .build(); + } + + while (dependencySource.getImportedFrom() != null) { + InputLocation importedFrom = dependencySource.getImportedFrom(); + + // Stop if the BOM is already in the list, no update necessary + if (Objects.equals(importedFrom.getSource().getModelId(), bomSource.getModelId())) { + return dependency; + } + + dependencySource = importedFrom.getSource(); + } + + // We modify the input location that is used for the whole file. + // This is likely correct because the POM hierarchy applies to the whole POM, not just one dependency. + return Dependency.newBuilder(dependency, true) + .importedFrom(new InputLocation(bomLocation)) + .build(); + } } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/DefaultDependencyManagementImporterTest.java similarity index 99% rename from maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java rename to maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/DefaultDependencyManagementImporterTest.java index ee656befbf49..39cbf65f1108 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/composition/DefaultDependencyManagementImporterTest.java +++ b/maven-api-impl/src/test/java/org/apache/maven/internal/impl/model/DefaultDependencyManagementImporterTest.java @@ -16,7 +16,7 @@ * specific language governing permissions and limitations * under the License. */ -package org.apache.maven.model.composition; +package org.apache.maven.internal.impl.model; import org.apache.maven.api.model.Dependency; import org.apache.maven.api.model.DependencyManagement; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index 8980a5f39c1b..9a102987c7e3 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -26,8 +26,6 @@ import org.apache.maven.api.model.Dependency; import org.apache.maven.api.model.DependencyManagement; import org.apache.maven.api.model.Exclusion; -import org.apache.maven.api.model.InputLocation; -import org.apache.maven.api.model.InputSource; import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblem; @@ -75,11 +73,6 @@ public Model importManagement( + toString(present) + ". Add the conflicting managed dependency directly " + "to the dependencyManagement section of the POM.")); } - - if (present == null && request.isLocationTracking()) { - Dependency updatedDependency = updateWithImportedFrom(dependency, source); - dependencies.put(key, updatedDependency); - } } } @@ -143,43 +136,4 @@ private boolean equals(Exclusion e1, Exclusion e2) { return Objects.equals(e1.getGroupId(), e2.getGroupId()) && Objects.equals(e1.getArtifactId(), e2.getArtifactId()); } - - static Dependency updateWithImportedFrom(Dependency dependency, DependencyManagement bom) { - // We are only interested in the InputSource, so the location of the element is sufficient - InputLocation dependencyLocation = dependency.getLocation(""); - InputLocation bomLocation = bom.getLocation(""); - - if (dependencyLocation == null || bomLocation == null) { - return dependency; - } - - InputSource dependencySource = dependencyLocation.getSource(); - InputSource bomSource = bomLocation.getSource(); - - // If the dependency and BOM have the same source, it means we found the root where the dependency is declared. - if (dependencySource == null - || bomSource == null - || Objects.equals(dependencySource.getModelId(), bomSource.getModelId())) { - return Dependency.newBuilder(dependency, true) - .importedFrom(bomLocation) - .build(); - } - - while (dependencySource.getImportedFrom() != null) { - InputLocation importedFrom = dependencySource.getImportedFrom(); - - // Stop if the BOM is already in the list, no update necessary - if (Objects.equals(importedFrom.getSource().getModelId(), bomSource.getModelId())) { - return dependency; - } - - dependencySource = importedFrom.getSource(); - } - - // We modify the input location that is used for the whole file. - // This is likely correct because the POM hierarchy applies to the whole POM, not just one dependency. - return Dependency.newBuilder(dependency, true) - .importedFrom(new InputLocation(bomLocation)) - .build(); - } } diff --git a/pom.xml b/pom.xml index 2a5b2c8b164c..2c1da8f2f369 100644 --- a/pom.xml +++ b/pom.xml @@ -161,6 +161,7 @@ under the License. ref/4-LATEST 2024-05-22T14:07:09Z + 3.26.0 9.7 1.14.18 2.0 @@ -606,6 +607,11 @@ under the License. ${hamcrestVersion} test + + org.assertj + assertj-core + ${assertjVersion} + org.codehaus.plexus plexus-testing diff --git a/src/mdo/model.vm b/src/mdo/model.vm index f53ebd8ee06d..4658eb1cee8c 100644 --- a/src/mdo/model.vm +++ b/src/mdo/model.vm @@ -485,8 +485,7 @@ public class ${class.name} } @Nonnull - public Builder importedFrom( InputLocation importedFrom ) - { + public Builder importedFrom(InputLocation importedFrom) { this.importedFrom = importedFrom; return this; }