This is an automated email from the ASF dual-hosted git repository. gnodet pushed a commit to branch master in repository https://gitbox.apache.org/repos/asf/maven.git
The following commit(s) were added to refs/heads/master by this push: new f153ac134 [MNG-7598] Fix compatibility issues with toolchains and settings (#971) f153ac134 is described below commit f153ac134c26ed89cdb7de1b294ecb613208c22b Author: Guillaume Nodet <gno...@gmail.com> AuthorDate: Fri Jan 27 15:56:16 2023 +0100 [MNG-7598] Fix compatibility issues with toolchains and settings (#971) * Split the header on two lines * Properly delegates equals/hashCode to the v4 models * Introduce object tracking in settings / toolchains * Get back to a single template for v3 models * Switch settings / toolchains mergers to deep merge * Fix binary compatibility with 3.x --- api/maven-api-model/src/main/mdo/maven.mdo | 9 +- api/maven-api-settings/src/main/mdo/settings.mdo | 6 +- api/maven-api-toolchain/pom.xml | 2 +- .../src/main/mdo/toolchains.mdo | 2 +- maven-core/pom.xml | 24 ++ maven-model-builder/pom.xml | 62 ++++ .../model/interpolation/ModelInterpolator.java | 6 +- .../apache/maven/model/merge/MavenModelMerger.java | 34 +++ .../normalization/DefaultModelNormalizer.java | 16 +- .../maven/model/normalization/ModelNormalizer.java | 12 +- maven-model/pom.xml | 36 ++- maven-plugin-api/pom.xml | 31 ++ maven-settings-builder/pom.xml | 5 + .../settings/building/DefaultSettingsBuilder.java | 15 +- .../maven/settings/io/DefaultSettingsReader.java | 6 +- .../maven/settings/io/DefaultSettingsWriter.java | 4 +- .../apache/maven/settings/io/SettingsReader.java | 2 +- .../apache/maven/settings/io/SettingsWriter.java | 2 +- .../maven/settings/merge/MavenSettingsMerger.java | 92 +++--- .../validation/DefaultSettingsValidator.java | 12 +- .../settings/validation/SettingsValidator.java | 2 +- .../validation/DefaultSettingsValidatorTest.java | 148 +++++----- maven-settings/pom.xml | 13 + .../java/org/apache/maven/settings/BaseObject.java | 61 ++++ maven-toolchain-builder/pom.xml | 26 ++ .../building/DefaultToolchainsBuilder.java | 18 +- .../toolchain/io/DefaultToolchainsReader.java | 6 +- .../toolchain/io/DefaultToolchainsWriter.java | 4 +- .../maven/toolchain/io/ToolchainsReader.java | 2 +- .../maven/toolchain/io/ToolchainsWriter.java | 2 +- .../toolchain/merge/MavenToolchainMerger.java | 54 +--- .../building/DefaultToolchainsBuilderTest.java | 101 +++---- .../toolchain/merge/MavenToolchainMergerTest.java | 104 +++---- maven-toolchain-model/pom.xml | 22 ++ .../apache/maven/toolchain/model/BaseObject.java | 61 ++++ pom.xml | 30 +- src/mdo/merger.vm | 20 +- src/mdo/model-v3-modified.vm | 319 --------------------- src/mdo/model-v3.vm | 145 +++++++--- src/mdo/model.vm | 3 +- src/mdo/reader-ex.vm | 3 +- src/mdo/reader-modified.vm | 3 +- src/mdo/reader.vm | 3 +- src/mdo/transformer.vm | 3 +- src/mdo/writer-ex.vm | 3 +- src/mdo/writer.vm | 3 +- 46 files changed, 823 insertions(+), 714 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index 19fa21357..2aa927e46 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -2527,6 +2527,13 @@ return groupId + ":" + artifactId; } + ]]> + </code> + </codeSegment> + <codeSegment> + <version>4.2.0+</version> + <code> + <![CDATA[ /** * @see java.lang.Object#equals(java.lang.Object) */ @@ -3240,7 +3247,7 @@ </fields> <codeSegments> <codeSegment> - <version>4.0.0+</version> + <version>4.2.0+</version> <code> <![CDATA[ /** diff --git a/api/maven-api-settings/src/main/mdo/settings.mdo b/api/maven-api-settings/src/main/mdo/settings.mdo index 93fa6034a..9e9221aaa 100644 --- a/api/maven-api-settings/src/main/mdo/settings.mdo +++ b/api/maven-api-settings/src/main/mdo/settings.mdo @@ -825,6 +825,8 @@ <field> <name>id</name> <version>1.0.0+</version> + <required>true</required> + <identifier>true</identifier> <description> <![CDATA[ A unique identifier for a repository. @@ -865,7 +867,7 @@ </fields> <codeSegments> <codeSegment> - <version>1.0.0+</version> + <version>1.0.0/1.1.0</version> <code> <![CDATA[ /** @@ -920,7 +922,7 @@ <!-- prevent Modello generation of an incorrect equals method. Could be avoided by using <identity/> tags to mark ID as the only identity field --> <codeSegments> <codeSegment> - <version>1.0.0+</version> + <version>1.0.0/1.1.0</version> <code> <![CDATA[ /** diff --git a/api/maven-api-toolchain/pom.xml b/api/maven-api-toolchain/pom.xml index f3e74c32e..5ed57c075 100644 --- a/api/maven-api-toolchain/pom.xml +++ b/api/maven-api-toolchain/pom.xml @@ -50,7 +50,7 @@ under the License. <goal>velocity</goal> </goals> <configuration> - <version>1.1.0</version> + <version>1.2.0</version> <velocityBasedir>${project.basedir}/../../src/mdo</velocityBasedir> <models> <model>src/main/mdo/toolchains.mdo</model> diff --git a/api/maven-api-toolchain/src/main/mdo/toolchains.mdo b/api/maven-api-toolchain/src/main/mdo/toolchains.mdo index 7090b9468..322d7501f 100644 --- a/api/maven-api-toolchain/src/main/mdo/toolchains.mdo +++ b/api/maven-api-toolchain/src/main/mdo/toolchains.mdo @@ -176,7 +176,7 @@ </fields> <codeSegments> <codeSegment> - <version>1.1.0+</version> + <version>1.2.0+</version> <comment>Generated hashCode() and equals() based on identifier also calls its super, which breaks comparison</comment> <code> <![CDATA[ diff --git a/maven-core/pom.xml b/maven-core/pom.xml index e2dd97ca3..8a30ed257 100644 --- a/maven-core/pom.xml +++ b/maven-core/pom.xml @@ -279,6 +279,30 @@ under the License. <artifactId>japicmp-maven-plugin</artifactId> <configuration> <parameter> + <includes> + <include>org.apache.maven.artifact</include> + <include>org.apache.maven.classrealm</include> + <include>org.apache.maven.cli</include> + <include>org.apache.maven.configuration</include> + <include>org.apache.maven.exception</include> + <include>org.apache.maven.execution</include> + <include>org.apache.maven.execution.scope</include> + <include>org.apache.maven.feature</include> + <include>org.apache.maven.graph</include> + <include>org.apache.maven.lifecycle</include> + <include>org.apache.maven.model</include> + <include>org.apache.maven.monitor</include> + <include>org.apache.maven.plugin</include> + <include>org.apache.maven.profiles</include> + <include>org.apache.maven.project</include> + <include>org.apache.maven.reporting</include> + <include>org.apache.maven.repository</include> + <include>org.apache.maven.rtinfo</include> + <include>org.apache.maven.rtinfo.internal</include> + <include>org.apache.maven.settings</include> + <include>org.apache.maven.toolchain</include> + <include>org.apache.maven.usability</include> + </includes> <!-- allowed non-binary backwards compatible changes --> <excludes> <!-- START default constructor on Plexus/JSR 330 components --> diff --git a/maven-model-builder/pom.xml b/maven-model-builder/pom.xml index 1a3850c3d..2173e2b25 100644 --- a/maven-model-builder/pom.xml +++ b/maven-model-builder/pom.xml @@ -108,6 +108,68 @@ under the License. <groupId>org.eclipse.sisu</groupId> <artifactId>sisu-maven-plugin</artifactId> </plugin> + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <configuration> + <oldVersion> + <dependency> + <groupId>${project.groupId}</groupId> + <artifactId>${project.artifactId}</artifactId> + <version>${maven.baseline}</version> + </dependency> + </oldVersion> + <parameter> + <excludes> + <exclude>org.apache.maven.model.building.DefaultModelBuilder#DefaultModelBuilder():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.building.DefaultModelProcessor#setModelLocator(org.apache.maven.model.locator.ModelLocator):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.building.DefaultModelProcessor#setModelReader(org.apache.maven.model.io.ModelReader):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.building.DefaultModelProcessor#DefaultModelProcessor():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.building.ModelCache#get(org.apache.maven.building.Source,java.lang.String):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.building.ModelCache#get(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.building.ModelCache#get(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,java.lang.String,java.lang.Object):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.building.ModelCache#put(org.apache.maven.building.Source,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.building.ModelCache#put(java.lang.String,java.lang.String,java.lang.String,org.apache.maven.model.building.ModelCacheTag,java.lang.Object):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.composition.DependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.composition.DefaultDependencyManagementImporter#importManagement(org.apache.maven.model.Model,java.util.List,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.inheritance.DefaultInheritanceAssembler</exclude> + <exclude>org.apache.maven.model.inheritance.InheritanceAssembler#assembleModelInheritance(org.apache.maven.model.Model,org.apache.maven.model.Model,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.interpolation.AbstractStringBasedModelInterpolator</exclude> + <exclude>org.apache.maven.model.interpolation.StringSearchModelInterpolator</exclude> + <exclude>org.apache.maven.model.interpolation.StringVisitorModelInterpolator</exclude> + <exclude>org.apache.maven.model.io.DefaultModelReader#DefaultModelReader():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.management.DefaultDependencyManagementInjector$ManagementModelMerger</exclude> + <exclude>org.apache.maven.model.management.DefaultPluginManagementInjector$ManagementModelMerger</exclude> + <exclude>org.apache.maven.model.merge.MavenModelMerger</exclude> + <exclude>org.apache.maven.model.normalization.DefaultModelNormalizer$DuplicateMerger#mergePlugin(org.apache.maven.model.Plugin,org.apache.maven.model.Plugin):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.normalization.DefaultModelNormalizer$DuplicateMerger:METHOD_REMOVED_IN_SUPERCLASS</exclude> + <exclude>org.apache.maven.model.path.DefaultModelPathTranslator#setPathTranslator(org.apache.maven.model.path.PathTranslator):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.path.DefaultModelPathTranslator#DefaultModelPathTranslator():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.path.DefaultModelUrlNormalizer#setUrlNormalizer(org.apache.maven.model.path.UrlNormalizer):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.path.DefaultModelUrlNormalizer#DefaultModelUrlNormalizer():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.path.ProfileActivationFilePathInterpolator#setPathTranslator(org.apache.maven.model.path.PathTranslator):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.path.ProfileActivationFilePathInterpolator#ProfileActivationFilePathInterpolator():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.profile.activation.FileProfileActivator#setProfileActivationFilePathInterpolator(org.apache.maven.model.path.ProfileActivationFilePathInterpolator):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.profile.activation.FileProfileActivator#FileProfileActivator():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.profile.DefaultProfileInjector</exclude> + <exclude>org.apache.maven.model.resolution.InvalidRepositoryException#getRepository():METHOD_RETURN_TYPE_CHANGED</exclude> + <exclude>org.apache.maven.model.resolution.InvalidRepositoryException#InvalidRepositoryException(java.lang.String,org.apache.maven.model.Repository,java.lang.Throwable):CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.resolution.InvalidRepositoryException#InvalidRepositoryException(java.lang.String,org.apache.maven.model.Repository):CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.resolution.ModelResolver#addRepository(org.apache.maven.api.model.Repository):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.resolution.ModelResolver#addRepository(org.apache.maven.api.model.Repository,boolean):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.resolution.ModelResolver#resolveModel(org.apache.maven.api.model.Parent,java.util.concurrent.atomic.AtomicReference):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.resolution.ModelResolver#resolveModel(org.apache.maven.api.model.Dependency,java.util.concurrent.atomic.AtomicReference):METHOD_NEW_DEFAULT</exclude> + <exclude>org.apache.maven.model.superpom.DefaultSuperPomProvider#getSuperModel(java.lang.String):METHOD_RETURN_TYPE_CHANGED</exclude> + <exclude>org.apache.maven.model.superpom.DefaultSuperPomProvider#setModelProcessor(org.apache.maven.model.building.ModelProcessor):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.superpom.DefaultSuperPomProvider#DefaultSuperPomProvider():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.model.superpom.SuperPomProvider#getSuperModel(java.lang.String):METHOD_RETURN_TYPE_CHANGED</exclude> + <exclude>org.apache.maven.model.validation.DefaultModelValidator#validateDependencyVersion(org.apache.maven.model.building.ModelProblemCollector,org.apache.maven.model.Dependency,java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.validation.ModelValidator#validateFileModel(org.apache.maven.model.Model,org.apache.maven.model.building.ModelBuildingRequest,org.apache.maven.model.building.ModelProblemCollector):METHOD_NEW_DEFAULT</exclude> + </excludes> + </parameter> + </configuration> + </plugin> </plugins> </build> diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java index 90b31acca..13add551f 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/ModelInterpolator.java @@ -20,7 +20,7 @@ package org.apache.maven.model.interpolation; import java.io.File; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -46,8 +46,8 @@ public interface ModelInterpolator { */ Model interpolateModel(Model model, File projectDir, ModelBuildingRequest request, ModelProblemCollector problems); - org.apache.maven.model.Model interpolateModel( - org.apache.maven.model.Model model, + org.apache.maven.api.model.Model interpolateModel( + org.apache.maven.api.model.Model model, File projectDir, ModelBuildingRequest request, ModelProblemCollector problems); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java b/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java index 7d4576ff9..d838ea6cd 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/merge/MavenModelMerger.java @@ -23,6 +23,7 @@ import java.util.LinkedHashMap; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Set; import org.apache.maven.api.model.BuildBase; @@ -66,6 +67,39 @@ public class MavenModelMerger extends MavenMerger { */ public static final String ARTIFACT_ID = "artifact-id"; + public MavenModelMerger() { + super(false); + } + + /** + * Merges the specified source object into the given target object. + * + * @param target The target object whose existing contents should be merged with the source, must not be + * <code>null</code>. + * @param source The (read-only) source object that should be merged into the target object, may be + * <code>null</code>. + * @param sourceDominant A flag indicating whether either the target object or the source object provides the + * dominant data. + * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific + * information along, may be <code>null</code>. + */ + public void merge( + org.apache.maven.model.Model target, + org.apache.maven.model.Model source, + boolean sourceDominant, + Map<?, ?> hints) { + Objects.requireNonNull(target, "target cannot be null"); + if (source == null) { + return; + } + target.update(merge(target.getDelegate(), source.getDelegate(), sourceDominant, hints)); + } + + @Override + public Model merge(Model target, Model source, boolean sourceDominant, Map<?, ?> hints) { + return super.merge(target, source, sourceDominant, hints); + } + @Override protected Model mergeModel(Model target, Model source, boolean sourceDominant, Map<Object, Object> context) { context.put(ARTIFACT_ID, target.getArtifactId()); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java index df9dfe190..0349ae56c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/DefaultModelNormalizer.java @@ -48,6 +48,18 @@ public class DefaultModelNormalizer implements ModelNormalizer { private DuplicateMerger merger = new DuplicateMerger(); + @Override + public void mergeDuplicates( + org.apache.maven.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems) { + model.update(mergeDuplicates(model.getDelegate(), request, problems)); + } + + @Override + public void injectDefaultValues( + org.apache.maven.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems) { + model.update(injectDefaultValues(model.getDelegate(), request, problems)); + } + @Override public Model mergeDuplicates(Model model, ModelBuildingRequest request, ModelProblemCollector problems) { Model.Builder builder = Model.newBuilder(model); @@ -127,9 +139,7 @@ public class DefaultModelNormalizer implements ModelNormalizer { private Dependency injectDependency(Dependency d) { // we cannot set this directly in the MDO due to the interactions with dependency management - return StringUtils.isEmpty(d.getScope()) - ? Dependency.newBuilder(d).scope("compile").build() - : d; + return StringUtils.isEmpty(d.getScope()) ? d.withScope("compile") : d; } /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java index 6ab915e8e..d98a6542a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/normalization/ModelNormalizer.java @@ -18,7 +18,7 @@ */ package org.apache.maven.model.normalization; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -37,7 +37,7 @@ public interface ModelNormalizer { * @param request The model building request that holds further settings, must not be {@code null}. * @param problems The container used to collect problems that were encountered, must not be {@code null}. */ - Model mergeDuplicates(Model model, ModelBuildingRequest request, ModelProblemCollector problems); + void mergeDuplicates(Model model, ModelBuildingRequest request, ModelProblemCollector problems); /** * Sets default values in the specified model that for technical reasons cannot be set directly in the Modello @@ -47,5 +47,11 @@ public interface ModelNormalizer { * @param request The model building request that holds further settings, must not be {@code null}. * @param problems The container used to collect problems that were encountered, must not be {@code null}. */ - Model injectDefaultValues(Model model, ModelBuildingRequest request, ModelProblemCollector problems); + void injectDefaultValues(Model model, ModelBuildingRequest request, ModelProblemCollector problems); + + org.apache.maven.api.model.Model mergeDuplicates( + org.apache.maven.api.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems); + + org.apache.maven.api.model.Model injectDefaultValues( + org.apache.maven.api.model.Model model, ModelBuildingRequest request, ModelProblemCollector problems); } diff --git a/maven-model/pom.xml b/maven-model/pom.xml index 56f03db5f..9194417af 100644 --- a/maven-model/pom.xml +++ b/maven-model/pom.xml @@ -81,7 +81,7 @@ under the License. <configuration> <version>4.1.0</version> <templates> - <template>model-v3-modified.vm</template> + <template>model-v3.vm</template> </templates> </configuration> </execution> @@ -114,6 +114,40 @@ under the License. </excludes> </configuration> </plugin> + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <configuration> + <parameter> + <excludes> + <exclude>org.apache.maven.model.*#setOtherLocation(java.lang.Object,org.apache.maven.model.InputLocation):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.ConfigurationContainer#isInheritanceApplied():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.ConfigurationContainer#setInherited(boolean):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.ConfigurationContainer#unsetInheritanceApplied():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Contributor#addProperty(java.lang.String,java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Dependency#clearManagementKey():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.ModelBase#addProperty(java.lang.String,java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.ModelBase#getReports():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.ModelBase#setReports(java.lang.Object):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Notifier#addConfiguration(java.lang.String,java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Plugin#getGoals():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Plugin#setGoals(java.lang.Object):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Reporting#flushReportPluginMap():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Reporting#getReportPluginsAsMap():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Resource#initMergeId():METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Scm#setChildScmConnectionInheritAppendPath(boolean):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Scm#setChildScmDeveloperConnectionInheritAppendPath(boolean):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Scm#setChildScmUrlInheritAppendPath(boolean):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.Site#setChildSiteUrlInheritAppendPath(boolean):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.io.xpp3.MavenXpp3Reader#contentTransformer</exclude> + <exclude>org.apache.maven.model.io.xpp3.MavenXpp3ReaderEx#contentTransformer</exclude> + <exclude>org.apache.maven.model.io.xpp3.MavenXpp3WriterEx#toString(org.apache.maven.model.InputLocation):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.io.xpp3.MavenXpp3WriterEx#writeXpp3DomToSerializer(org.codehaus.plexus.util.xml.Xpp3Dom,org.codehaus.plexus.util.xml.pull.XmlSerializer):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.model.merge.ModelMerger</exclude> + </excludes> + </parameter> + </configuration> + </plugin> </plugins> </build> diff --git a/maven-plugin-api/pom.xml b/maven-plugin-api/pom.xml index 420df66d1..514c4c9fe 100644 --- a/maven-plugin-api/pom.xml +++ b/maven-plugin-api/pom.xml @@ -104,6 +104,37 @@ under the License. <plugin> <groupId>com.github.siom79.japicmp</groupId> <artifactId>japicmp-maven-plugin</artifactId> + <configuration> + <parameter> + <excludes> + <exclude>org.apache.maven.monitor.logging.DefaultLog</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Execution#addGoal(java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Execution#getConfiguration():METHOD_RETURN_TYPE_CHANGED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Execution#removeGoal(java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Execution#setConfiguration(java.lang.Object):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Execution#setGoals(java.util.List):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Execution#Execution():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.io.xpp3.LifecycleMappingsXpp3Reader#contentTransformer</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Lifecycle#addPhase(org.apache.maven.plugin.lifecycle.Phase):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Lifecycle#removePhase(org.apache.maven.plugin.lifecycle.Phase):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Lifecycle#setId(java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Lifecycle#setPhases(java.util.List):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Lifecycle#Lifecycle():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#addLifecycle(org.apache.maven.plugin.lifecycle.Lifecycle):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#removeLifecycle(org.apache.maven.plugin.lifecycle.Lifecycle):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#setLifecycles(java.util.List):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#setModelEncoding(java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.LifecycleConfiguration#LifecycleConfiguration():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Phase#addExecution(org.apache.maven.plugin.lifecycle.Execution):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Phase#getConfiguration():METHOD_RETURN_TYPE_CHANGED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Phase#removeExecution(org.apache.maven.plugin.lifecycle.Execution):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Phase#setConfiguration(java.lang.Object):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Phase#setExecutions(java.util.List):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Phase#setId(java.lang.String):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.plugin.lifecycle.Phase#Phase():CONSTRUCTOR_REMOVED</exclude> + </excludes> + </parameter> + </configuration> </plugin> </plugins> </build> diff --git a/maven-settings-builder/pom.xml b/maven-settings-builder/pom.xml index 0b774540b..1e1c6a499 100644 --- a/maven-settings-builder/pom.xml +++ b/maven-settings-builder/pom.xml @@ -75,6 +75,11 @@ under the License. <groupId>org.eclipse.sisu</groupId> <artifactId>sisu-maven-plugin</artifactId> </plugin> + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <configuration /> + </plugin> </plugins> </build> diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java index 5b80c59d1..67acbafac 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuilder.java @@ -30,9 +30,9 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import org.apache.maven.api.settings.Settings; import org.apache.maven.building.FileSource; import org.apache.maven.building.Source; +import org.apache.maven.settings.Settings; import org.apache.maven.settings.TrackableBase; import org.apache.maven.settings.io.SettingsParseException; import org.apache.maven.settings.io.SettingsReader; @@ -95,7 +95,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder { Source userSettingsSource = getSettingsSource(request.getUserSettingsFile(), request.getUserSettingsSource()); Settings userSettings = readSettings(userSettingsSource, request, problems); - userSettings = settingsMerger.merge(userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL); + settingsMerger.merge(userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL); problems.setSource(""); @@ -106,7 +106,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder { if (localRepository != null && localRepository.length() > 0) { File file = new File(localRepository); if (!file.isAbsolute() && file.getPath().startsWith(File.separator)) { - userSettings = userSettings.withLocalRepository(file.getAbsolutePath()); + userSettings.setLocalRepository(file.getAbsolutePath()); } } @@ -114,8 +114,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder { throw new SettingsBuildingException(problems.getProblems()); } - return new DefaultSettingsBuildingResult( - new org.apache.maven.settings.Settings(userSettings), problems.getProblems()); + return new DefaultSettingsBuildingResult(userSettings, problems.getProblems()); } private boolean hasErrors(List<SettingsProblem> problems) { @@ -142,7 +141,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder { private Settings readSettings( Source settingsSource, SettingsBuildingRequest request, DefaultSettingsProblemCollector problems) { if (settingsSource == null) { - return Settings.newInstance(); + return new Settings(); } problems.setSource(settingsSource.getLocation()); @@ -169,7 +168,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder { e.getLineNumber(), e.getColumnNumber(), e); - return Settings.newInstance(); + return new Settings(); } catch (IOException e) { problems.add( SettingsProblem.Severity.FATAL, @@ -177,7 +176,7 @@ public class DefaultSettingsBuilder implements SettingsBuilder { -1, -1, e); - return Settings.newInstance(); + return new Settings(); } settingsValidator.validate(settings, problems); diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java index accb57bd9..56508b8d3 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsReader.java @@ -28,7 +28,7 @@ import java.io.Reader; import java.util.Map; import java.util.Objects; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.Settings; import org.apache.maven.settings.v4.SettingsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -54,7 +54,7 @@ public class DefaultSettingsReader implements SettingsReader { Objects.requireNonNull(input, "input cannot be null"); try (Reader in = input) { - return new SettingsXpp3Reader().read(in, isStrict(options)); + return new Settings(new SettingsXpp3Reader().read(in, isStrict(options))); } catch (XmlPullParserException e) { throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); } @@ -65,7 +65,7 @@ public class DefaultSettingsReader implements SettingsReader { Objects.requireNonNull(input, "input cannot be null"); try (InputStream in = input) { - return new SettingsXpp3Reader().read(in, isStrict(options)); + return new Settings(new SettingsXpp3Reader().read(in, isStrict(options))); } catch (XmlPullParserException e) { throw new SettingsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); } diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java index a8d6bca0c..4f4a7b293 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/DefaultSettingsWriter.java @@ -29,7 +29,7 @@ import java.io.Writer; import java.util.Map; import java.util.Objects; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.Settings; import org.apache.maven.settings.v4.SettingsXpp3Writer; import org.codehaus.plexus.util.WriterFactory; @@ -58,7 +58,7 @@ public class DefaultSettingsWriter implements SettingsWriter { Objects.requireNonNull(settings, "settings cannot be null"); try (Writer out = output) { - new SettingsXpp3Writer().write(out, settings); + new SettingsXpp3Writer().write(out, settings.getDelegate()); } } diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java index 257b097a6..5bb7d6365 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsReader.java @@ -24,7 +24,7 @@ import java.io.InputStream; import java.io.Reader; import java.util.Map; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.Settings; /** * Handles deserialization of settings from some kind of textual format like XML. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java index 8a7ced6b9..caff9f44e 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/io/SettingsWriter.java @@ -24,7 +24,7 @@ import java.io.OutputStream; import java.io.Writer; import java.util.Map; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.Settings; /** * Handles serialization of settings into some kind of textual format like XML. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java index 942922795..01f751b7f 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/merge/MavenSettingsMerger.java @@ -19,16 +19,12 @@ package org.apache.maven.settings.merge; import java.util.ArrayList; -import java.util.Collection; import java.util.HashMap; import java.util.List; import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; -import java.util.stream.Stream; -import org.apache.maven.api.settings.IdentifiableBase; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.IdentifiableBase; +import org.apache.maven.settings.Settings; import org.codehaus.plexus.util.StringUtils; /** @@ -44,44 +40,54 @@ public class MavenSettingsMerger { * @param recessive * @param recessiveSourceLevel */ - public Settings merge(Settings dominant, Settings recessive, String recessiveSourceLevel) { - if (dominant == null) { - return recessive; - } else if (recessive == null) { - return dominant; + public void merge(Settings dominant, Settings recessive, String recessiveSourceLevel) { + if (dominant == null || recessive == null) { + return; } recessive.setSourceLevel(recessiveSourceLevel); - Settings.Builder merged = Settings.newBuilder(dominant); - List<String> dominantActiveProfiles = dominant.getActiveProfiles(); List<String> recessiveActiveProfiles = recessive.getActiveProfiles(); - List<String> mergedActiveProfiles = Stream.of(dominantActiveProfiles, recessiveActiveProfiles) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - merged.activeProfiles(mergedActiveProfiles); + + if (recessiveActiveProfiles != null) { + if (dominantActiveProfiles == null) { + dominantActiveProfiles = new ArrayList<>(); + dominant.setActiveProfiles(dominantActiveProfiles); + } + + for (String profileId : recessiveActiveProfiles) { + if (!dominantActiveProfiles.contains(profileId)) { + dominantActiveProfiles.add(profileId); + } + } + } List<String> dominantPluginGroupIds = dominant.getPluginGroups(); + List<String> recessivePluginGroupIds = recessive.getPluginGroups(); - List<String> mergedPluginGroupIds = Stream.of(dominantPluginGroupIds, recessivePluginGroupIds) - .flatMap(Collection::stream) - .distinct() - .collect(Collectors.toList()); - merged.pluginGroups(mergedPluginGroupIds); - - String localRepository = StringUtils.isEmpty(dominant.getLocalRepository()) - ? recessive.getLocalRepository() - : dominant.getLocalRepository(); - merged.localRepository(localRepository); - - merged.mirrors(shallowMergeById(dominant.getMirrors(), recessive.getMirrors(), recessiveSourceLevel)); - merged.servers(shallowMergeById(dominant.getServers(), recessive.getServers(), recessiveSourceLevel)); - merged.proxies(shallowMergeById(dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel)); - merged.profiles(shallowMergeById(dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel)); - - return merged.build(); + + if (recessivePluginGroupIds != null) { + if (dominantPluginGroupIds == null) { + dominantPluginGroupIds = new ArrayList<>(); + dominant.setPluginGroups(dominantPluginGroupIds); + } + + for (String pluginGroupId : recessivePluginGroupIds) { + if (!dominantPluginGroupIds.contains(pluginGroupId)) { + dominantPluginGroupIds.add(pluginGroupId); + } + } + } + + if (StringUtils.isEmpty(dominant.getLocalRepository())) { + dominant.setLocalRepository(recessive.getLocalRepository()); + } + + shallowMergeById(dominant.getMirrors(), recessive.getMirrors(), recessiveSourceLevel); + shallowMergeById(dominant.getServers(), recessive.getServers(), recessiveSourceLevel); + shallowMergeById(dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel); + shallowMergeById(dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel); } /** @@ -89,18 +95,20 @@ public class MavenSettingsMerger { * @param recessive * @param recessiveSourceLevel */ - private static <T extends IdentifiableBase> List<T> shallowMergeById( + private static <T extends IdentifiableBase> void shallowMergeById( List<T> dominant, List<T> recessive, String recessiveSourceLevel) { - Set<String> dominantIds = dominant.stream().map(IdentifiableBase::getId).collect(Collectors.toSet()); - final List<T> merged = new ArrayList<>(dominant.size() + recessive.size()); - merged.addAll(dominant); + Map<String, T> dominantById = mapById(dominant); + final List<T> identifiables = new ArrayList<>(recessive.size()); + for (T identifiable : recessive) { - if (!dominantIds.contains(identifiable.getId())) { + if (!dominantById.containsKey(identifiable.getId())) { identifiable.setSourceLevel(recessiveSourceLevel); - merged.add(identifiable); + + identifiables.add(identifiable); } } - return merged; + + dominant.addAll(0, identifiables); } /** diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java index 36556e969..11ec66d61 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/DefaultSettingsValidator.java @@ -25,12 +25,12 @@ import java.util.HashSet; import java.util.List; import java.util.Set; -import org.apache.maven.api.settings.Mirror; -import org.apache.maven.api.settings.Profile; -import org.apache.maven.api.settings.Proxy; -import org.apache.maven.api.settings.Repository; -import org.apache.maven.api.settings.Server; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Profile; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Repository; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; import org.apache.maven.settings.building.SettingsProblem.Severity; import org.apache.maven.settings.building.SettingsProblemCollector; import org.codehaus.plexus.util.StringUtils; diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java index 7ec8e3756..66bd2f738 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/validation/SettingsValidator.java @@ -18,7 +18,7 @@ */ package org.apache.maven.settings.validation; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.Settings; import org.apache.maven.settings.building.SettingsProblemCollector; /** diff --git a/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java b/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java index 18c33c20a..58af79379 100644 --- a/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java +++ b/maven-settings-builder/src/test/java/org/apache/maven/settings/validation/DefaultSettingsValidatorTest.java @@ -19,16 +19,14 @@ package org.apache.maven.settings.validation; import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; import java.util.List; -import org.apache.maven.api.settings.Mirror; -import org.apache.maven.api.settings.Profile; -import org.apache.maven.api.settings.Proxy; -import org.apache.maven.api.settings.Repository; -import org.apache.maven.api.settings.Server; -import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Profile; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Repository; +import org.apache.maven.settings.Server; +import org.apache.maven.settings.Settings; import org.apache.maven.settings.building.SettingsProblem.Severity; import org.apache.maven.settings.building.SettingsProblemCollector; import org.junit.jupiter.api.AfterEach; @@ -61,29 +59,26 @@ public class DefaultSettingsValidatorTest { @Test public void testValidate() { - Profile prof = Profile.newInstance().withId("xxx"); - Settings model = Settings.newInstance().withProfiles(Collections.singletonList(prof)); + Settings model = new Settings(); + Profile prof = new Profile(); + prof.setId("xxx"); + model.addProfile(prof); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(model, problems); assertEquals(0, problems.messages.size()); - Repository repo = Repository.newInstance(); - prof = prof.withRepositories(Collections.singletonList(repo)); - model = model.withProfiles(Collections.singletonList(prof)); + Repository repo = new Repository(); + prof.addRepository(repo); problems = new SimpleProblemCollector(); validator.validate(model, problems); assertEquals(2, problems.messages.size()); - repo = repo.withUrl("http://xxx.xxx.com"); - prof = prof.withRepositories(Collections.singletonList(repo)); - model = model.withProfiles(Collections.singletonList(prof)); + repo.setUrl("http://xxx.xxx.com"); problems = new SimpleProblemCollector(); validator.validate(model, problems); assertEquals(1, problems.messages.size()); - repo = repo.withId("xxx"); - prof = prof.withRepositories(Collections.singletonList(repo)); - model = model.withProfiles(Collections.singletonList(prof)); + repo.setId("xxx"); problems = new SimpleProblemCollector(); validator.validate(model, problems); assertEquals(0, problems.messages.size()); @@ -91,14 +86,15 @@ public class DefaultSettingsValidatorTest { @Test public void testValidateMirror() throws Exception { - Mirror mirror1 = Mirror.newBuilder().id("local").build(); - Mirror mirror2 = Mirror.newBuilder() - .id("illegal\\:/chars") - .url("http://void") - .mirrorOf("void") - .build(); - Settings settings = - Settings.newBuilder().mirrors(Arrays.asList(mirror1, mirror2)).build(); + Settings settings = new Settings(); + Mirror mirror = new Mirror(); + mirror.setId("local"); + settings.addMirror(mirror); + mirror = new Mirror(); + mirror.setId("illegal\\:/chars"); + mirror.setUrl("http://void"); + mirror.setMirrorOf("void"); + settings.addMirror(mirror); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(settings, problems); @@ -111,16 +107,16 @@ public class DefaultSettingsValidatorTest { @Test public void testValidateRepository() throws Exception { - Repository repo1 = Repository.newBuilder().id("local").build(); - Repository repo2 = Repository.newBuilder() - .id("illegal\\:/chars") - .url("http://void") - .build(); - Profile profile = - Profile.newBuilder().repositories(Arrays.asList(repo1, repo2)).build(); - Settings settings = Settings.newBuilder() - .profiles(Collections.singletonList(profile)) - .build(); + Profile profile = new Profile(); + Repository repo = new Repository(); + repo.setId("local"); + profile.addRepository(repo); + repo = new Repository(); + repo.setId("illegal\\:/chars"); + repo.setUrl("http://void"); + profile.addRepository(repo); + Settings settings = new Settings(); + settings.addProfile(profile); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(settings, problems); @@ -137,10 +133,13 @@ public class DefaultSettingsValidatorTest { @Test public void testValidateUniqueServerId() throws Exception { - Server server1 = Server.newBuilder().id("test").build(); - Server server2 = Server.newBuilder().id("test").build(); - Settings settings = - Settings.newBuilder().servers(Arrays.asList(server1, server2)).build(); + Settings settings = new Settings(); + Server server1 = new Server(); + server1.setId("test"); + settings.addServer(server1); + Server server2 = new Server(); + server2.setId("test"); + settings.addServer(server2); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(settings, problems); @@ -151,11 +150,13 @@ public class DefaultSettingsValidatorTest { @Test public void testValidateUniqueProfileId() throws Exception { - Profile profile1 = Profile.newBuilder().id("test").build(); - Profile profile2 = Profile.newBuilder().id("test").build(); - Settings settings = Settings.newBuilder() - .profiles(Arrays.asList(profile1, profile2)) - .build(); + Settings settings = new Settings(); + Profile profile1 = new Profile(); + profile1.setId("test"); + settings.addProfile(profile1); + Profile profile2 = new Profile(); + profile2.setId("test"); + settings.addProfile(profile2); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(settings, problems); @@ -167,17 +168,18 @@ public class DefaultSettingsValidatorTest { @Test public void testValidateUniqueRepositoryId() throws Exception { - Repository repo1 = - Repository.newBuilder().id("test").url("http://apache.org/").build(); - Repository repo2 = - Repository.newBuilder().id("test").url("http://apache.org/").build(); - Profile profile = Profile.newBuilder() - .id("pro") - .repositories(Arrays.asList(repo1, repo2)) - .build(); - Settings settings = Settings.newBuilder() - .profiles(Collections.singletonList(profile)) - .build(); + Settings settings = new Settings(); + Profile profile = new Profile(); + profile.setId("pro"); + settings.addProfile(profile); + Repository repo1 = new Repository(); + repo1.setUrl("http://apache.org/"); + repo1.setId("test"); + profile.addRepository(repo1); + Repository repo2 = new Repository(); + repo2.setUrl("http://apache.org/"); + repo2.setId("test"); + profile.addRepository(repo2); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(settings, problems); @@ -190,37 +192,27 @@ public class DefaultSettingsValidatorTest { @Test public void testValidateUniqueProxyId() throws Exception { - Proxy proxy = Proxy.newBuilder().id("foo").host("www.example.com").build(); - Settings settings = - Settings.newBuilder().proxies(Arrays.asList(proxy, proxy)).build(); + Settings settings = new Settings(); + Proxy proxy = new Proxy(); + String id = "foo"; + proxy.setId(id); + proxy.setHost("www.example.com"); + settings.addProxy(proxy); + settings.addProxy(proxy); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(settings, problems); assertEquals(1, problems.messages.size()); assertContains( problems.messages.get(0), - "'proxies.proxy.id' must be unique" + " but found duplicate proxy with id foo"); - } - - @Test - public void testValidateUniqueProxyNullId() throws Exception { - Proxy proxy = Proxy.newBuilder(false).host("www.example.com").build(); - Settings settings = - Settings.newBuilder().proxies(Arrays.asList(proxy, proxy)).build(); - - SimpleProblemCollector problems = new SimpleProblemCollector(); - validator.validate(settings, problems); - assertEquals(1, problems.messages.size()); - assertContains( - problems.messages.get(0), - "'proxies.proxy.id' must be unique" + " but found duplicate proxy with id null"); + "'proxies.proxy.id' must be unique" + " but found duplicate proxy with id " + id); } @Test public void testValidateProxy() throws Exception { - Proxy proxy = Proxy.newBuilder().build(); - Settings settings = - Settings.newBuilder().proxies(Collections.singletonList(proxy)).build(); + Settings settings = new Settings(); + Proxy proxy1 = new Proxy(); + settings.addProxy(proxy1); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate(settings, problems); diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml index be088709b..bfb45eeb3 100644 --- a/maven-settings/pom.xml +++ b/maven-settings/pom.xml @@ -84,6 +84,19 @@ under the License. </execution> </executions> </plugin> + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <configuration> + <parameter> + <excludes> + <exclude>org.apache.maven.settings.io.xpp3.SettingsXpp3Reader#contentTransformer</exclude> + <exclude>org.apache.maven.settings.RuntimeInfo</exclude> + <exclude>org.apache.maven.settings.Settings#setModelEncoding(java.lang.String):METHOD_REMOVED</exclude> + </excludes> + </parameter> + </configuration> + </plugin> </plugins> </build> </project> diff --git a/maven-settings/src/main/java/org/apache/maven/settings/BaseObject.java b/maven-settings/src/main/java/org/apache/maven/settings/BaseObject.java new file mode 100644 index 000000000..7b66110a8 --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/BaseObject.java @@ -0,0 +1,61 @@ +/* + * 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.settings; + +import java.io.Serializable; + +public abstract class BaseObject implements Serializable, Cloneable { + protected transient ChildrenTracking childrenTracking; + + protected Object delegate; + + public BaseObject() {} + + public BaseObject(Object delegate, BaseObject parent) { + this.delegate = delegate; + this.childrenTracking = parent != null ? parent::replace : null; + } + + public BaseObject(Object delegate, ChildrenTracking parent) { + this.delegate = delegate; + this.childrenTracking = parent; + } + + public Object getDelegate() { + return delegate; + } + + public void update(Object newDelegate) { + if (delegate != newDelegate) { + if (childrenTracking != null) { + childrenTracking.replace(delegate, newDelegate); + } + delegate = newDelegate; + } + } + + protected boolean replace(Object oldDelegate, Object newDelegate) { + return false; + } + + @FunctionalInterface + protected interface ChildrenTracking { + boolean replace(Object oldDelegate, Object newDelegate); + } +} diff --git a/maven-toolchain-builder/pom.xml b/maven-toolchain-builder/pom.xml index cbb5b9a89..9b4aca4cd 100644 --- a/maven-toolchain-builder/pom.xml +++ b/maven-toolchain-builder/pom.xml @@ -64,6 +64,32 @@ under the License. <groupId>org.eclipse.sisu</groupId> <artifactId>sisu-maven-plugin</artifactId> </plugin> + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <configuration> + <parameter> + <includes> + <include>org.apache.maven.toolchain.building</include> + <include>org.apache.maven.toolchain.io</include> + <include>org.apache.maven.toolchain.io.xpp3</include> + <include>org.apache.maven.toolchain.merge</include> + </includes> + <excludes> + <exclude>org.apache.maven.toolchain.building.DefaultToolchainsBuilder#DefaultToolchainsBuilder():CONSTRUCTOR_REMOVED</exclude> + <exclude>org.apache.maven.toolchain.merge.MavenToolchainMerger#getToolchainModelKey(org.apache.maven.toolchain.model.ToolchainModel):METHOD_REMOVED</exclude> + <exclude>org.apache.maven.toolchain.merge.MavenToolchainMerger#mergeToolchainModelConfiguration(org.apache.maven.toolchain.model.ToolchainModel,org.apache.maven.toolchain.model.ToolchainModel):METHOD_REMOVED</exclude> + </excludes> + </parameter> + <oldVersion> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${maven.baseline}</version> + </dependency> + </oldVersion> + </configuration> + </plugin> </plugins> </build> diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java index 48ca8aaa7..3e7e40d84 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilder.java @@ -29,8 +29,6 @@ import java.util.Collections; import java.util.List; import java.util.Map; -import org.apache.maven.api.toolchain.PersistedToolchains; -import org.apache.maven.api.toolchain.TrackableBase; import org.apache.maven.building.Problem; import org.apache.maven.building.ProblemCollector; import org.apache.maven.building.ProblemCollectorFactory; @@ -39,6 +37,8 @@ import org.apache.maven.toolchain.io.ToolchainsParseException; import org.apache.maven.toolchain.io.ToolchainsReader; import org.apache.maven.toolchain.io.ToolchainsWriter; import org.apache.maven.toolchain.merge.MavenToolchainMerger; +import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.toolchain.model.TrackableBase; import org.codehaus.plexus.interpolation.EnvarBasedValueSource; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.RegexBasedInterpolator; @@ -69,19 +69,17 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder { PersistedToolchains userToolchains = readToolchains(request.getUserToolchainsSource(), request, problems); - PersistedToolchains merged = - toolchainsMerger.merge(userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL); + toolchainsMerger.merge(userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL); problems.setSource(""); - merged = interpolate(merged, problems); + userToolchains = interpolate(userToolchains, problems); if (hasErrors(problems.getProblems())) { throw new ToolchainsBuildingException(problems.getProblems()); } - return new DefaultToolchainsBuildingResult( - new org.apache.maven.toolchain.model.PersistedToolchains(merged), problems.getProblems()); + return new DefaultToolchainsBuildingResult(userToolchains, problems.getProblems()); } private PersistedToolchains interpolate(PersistedToolchains toolchains, ProblemCollector problems) { @@ -143,7 +141,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder { private PersistedToolchains readToolchains( Source toolchainsSource, ToolchainsBuildingRequest request, ProblemCollector problems) { if (toolchainsSource == null) { - return PersistedToolchains.newInstance(); + return new PersistedToolchains(); } PersistedToolchains toolchains; @@ -167,7 +165,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder { e.getLineNumber(), e.getColumnNumber(), e); - return PersistedToolchains.newInstance(); + return new PersistedToolchains(); } catch (IOException e) { problems.add( Problem.Severity.FATAL, @@ -175,7 +173,7 @@ public class DefaultToolchainsBuilder implements ToolchainsBuilder { -1, -1, e); - return PersistedToolchains.newInstance(); + return new PersistedToolchains(); } return toolchains; diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java index 8bda68f91..a361775b8 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsReader.java @@ -28,7 +28,7 @@ import java.io.Reader; import java.util.Map; import java.util.Objects; -import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.model.PersistedToolchains; import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -55,7 +55,7 @@ public class DefaultToolchainsReader implements ToolchainsReader { Objects.requireNonNull(input, "input cannot be null"); try (Reader in = input) { - return new MavenToolchainsXpp3Reader().read(in, isStrict(options)); + return new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in, isStrict(options))); } catch (XmlPullParserException e) { throw new ToolchainsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); } @@ -66,7 +66,7 @@ public class DefaultToolchainsReader implements ToolchainsReader { Objects.requireNonNull(input, "input cannot be null"); try (InputStream in = input) { - return new MavenToolchainsXpp3Reader().read(in, isStrict(options)); + return new PersistedToolchains(new MavenToolchainsXpp3Reader().read(in, isStrict(options))); } catch (XmlPullParserException e) { throw new ToolchainsParseException(e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e); } diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java index 3dda1b2bc..7f831df52 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/DefaultToolchainsWriter.java @@ -26,7 +26,7 @@ import java.io.Writer; import java.util.Map; import java.util.Objects; -import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.model.PersistedToolchains; import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer; /** @@ -45,7 +45,7 @@ public class DefaultToolchainsWriter implements ToolchainsWriter { Objects.requireNonNull(toolchains, "toolchains cannot be null"); try (Writer out = output) { - new MavenToolchainsXpp3Writer().write(out, toolchains); + new MavenToolchainsXpp3Writer().write(out, toolchains.getDelegate()); } } } diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java index 0feedb80d..eeb23c14b 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsReader.java @@ -24,7 +24,7 @@ import java.io.InputStream; import java.io.Reader; import java.util.Map; -import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.model.PersistedToolchains; /** * Handles deserialization of toolchains from some kind of textual format like XML. diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java index c58dc42af..55f851e31 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/io/ToolchainsWriter.java @@ -22,7 +22,7 @@ import java.io.IOException; import java.io.Writer; import java.util.Map; -import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.model.PersistedToolchains; /** * Handles serialization of toolchains into some kind of textual format like XML. diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java index b0928b004..642df8ebd 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/merge/MavenToolchainMerger.java @@ -18,14 +18,7 @@ */ package org.apache.maven.toolchain.merge; -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; - -import org.apache.maven.api.toolchain.PersistedToolchains; -import org.apache.maven.api.toolchain.ToolchainModel; -import org.apache.maven.api.xml.XmlNode; +import org.apache.maven.toolchain.model.PersistedToolchains; /** * @@ -34,51 +27,14 @@ import org.apache.maven.api.xml.XmlNode; */ public class MavenToolchainMerger { - public PersistedToolchains merge( - PersistedToolchains dominant, PersistedToolchains recessive, String recessiveSourceLevel) { + public void merge(PersistedToolchains dominant, PersistedToolchains recessive, String recessiveSourceLevel) { if (dominant == null || recessive == null) { - return dominant; + return; } recessive.setSourceLevel(recessiveSourceLevel); - return shallowMerge(dominant.getToolchains(), recessive.getToolchains(), recessiveSourceLevel); - } - - private PersistedToolchains shallowMerge( - List<ToolchainModel> dominant, List<ToolchainModel> recessive, String recessiveSourceLevel) { - Map<Object, ToolchainModel> merged = new LinkedHashMap<>(); - - for (ToolchainModel dominantModel : dominant) { - Object key = getToolchainModelKey(dominantModel); - - merged.put(key, dominantModel); - } - - for (ToolchainModel recessiveModel : recessive) { - Object key = getToolchainModelKey(recessiveModel); - - ToolchainModel dominantModel = merged.get(key); - if (dominantModel == null) { - recessiveModel.setSourceLevel(recessiveSourceLevel); - merged.put(key, recessiveModel); - } else { - merged.put(key, mergeToolchainModelConfiguration(dominantModel, recessiveModel)); - } - } - return PersistedToolchains.newBuilder() - .toolchains(new ArrayList<>(merged.values())) - .build(); - } - - protected ToolchainModel mergeToolchainModelConfiguration(ToolchainModel target, ToolchainModel source) { - XmlNode src = source.getConfiguration(); - XmlNode tgt = target.getConfiguration(); - XmlNode merged = XmlNode.merge(tgt, src); - return target.withConfiguration(merged); - } - - protected Object getToolchainModelKey(ToolchainModel model) { - return model; + dominant.update(new org.apache.maven.toolchain.v4.MavenToolchainsMerger() + .merge(dominant.getDelegate(), recessive.getDelegate(), true, null)); } } diff --git a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java index 33ebfd134..fc6c31634 100644 --- a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java +++ b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/building/DefaultToolchainsBuilderTest.java @@ -23,15 +23,16 @@ import java.io.InputStream; import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Properties; -import org.apache.maven.api.toolchain.PersistedToolchains; -import org.apache.maven.api.toolchain.ToolchainModel; import org.apache.maven.building.StringSource; -import org.apache.maven.internal.xml.XmlNodeImpl; import org.apache.maven.toolchain.io.DefaultToolchainsReader; import org.apache.maven.toolchain.io.DefaultToolchainsWriter; import org.apache.maven.toolchain.io.ToolchainsParseException; +import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.toolchain.model.ToolchainModel; import org.codehaus.plexus.interpolation.os.OperatingSystemUtils; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; @@ -81,13 +82,13 @@ public class DefaultToolchainsBuilderTest { ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource(new StringSource("")); - Map<String, String> props = new HashMap<>(); + Properties props = new Properties(); props.put("key", "user_value"); - ToolchainModel toolchain = - ToolchainModel.newBuilder().type("TYPE").provides(props).build(); - PersistedToolchains userResult = PersistedToolchains.newBuilder() - .toolchains(Collections.singletonList(toolchain)) - .build(); + ToolchainModel toolchain = new ToolchainModel(); + toolchain.setType("TYPE"); + toolchain.setProvides(props); + PersistedToolchains userResult = new PersistedToolchains(); + userResult.setToolchains(Collections.singletonList(toolchain)); doReturn(userResult) .when(toolchainsReader) .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap()); @@ -113,13 +114,13 @@ public class DefaultToolchainsBuilderTest { ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setGlobalToolchainsSource(new StringSource("")); - Map<String, String> props = new HashMap<>(); + Properties props = new Properties(); props.put("key", "global_value"); - ToolchainModel toolchain = - ToolchainModel.newBuilder().type("TYPE").provides(props).build(); - PersistedToolchains globalResult = PersistedToolchains.newBuilder() - .toolchains(Collections.singletonList(toolchain)) - .build(); + ToolchainModel toolchain = new ToolchainModel(); + toolchain.setType("TYPE"); + toolchain.setProvides(props); + PersistedToolchains globalResult = new PersistedToolchains(); + globalResult.setToolchains(Collections.singletonList(toolchain)); doReturn(globalResult) .when(toolchainsReader) .read(any(InputStream.class), ArgumentMatchers.<String, Object>anyMap()); @@ -146,20 +147,21 @@ public class DefaultToolchainsBuilderTest { request.setGlobalToolchainsSource(new StringSource("")); request.setUserToolchainsSource(new StringSource("")); - Map<String, String> props = new HashMap<>(); + Properties props = new Properties(); props.put("key", "user_value"); - ToolchainModel toolchain = - ToolchainModel.newBuilder().type("TYPE").provides(props).build(); - PersistedToolchains userResult = PersistedToolchains.newBuilder() - .toolchains(Collections.singletonList(toolchain)) - .build(); + ToolchainModel toolchain = new ToolchainModel(); + toolchain.setType("TYPE"); + toolchain.setProvides(props); + PersistedToolchains userResult = new PersistedToolchains(); + userResult.setToolchains(Collections.singletonList(toolchain)); - props = new HashMap<>(); + props = new Properties(); props.put("key", "global_value"); - toolchain = ToolchainModel.newBuilder().type("TYPE").provides(props).build(); - PersistedToolchains globalResult = PersistedToolchains.newBuilder() - .toolchains(Collections.singletonList(toolchain)) - .build(); + toolchain = new ToolchainModel(); + toolchain.setType("TYPE"); + toolchain.setProvides(props); + PersistedToolchains globalResult = new PersistedToolchains(); + globalResult.setToolchains(Collections.singletonList(toolchain)); doReturn(globalResult) .doReturn(userResult) @@ -234,19 +236,18 @@ public class DefaultToolchainsBuilderTest { ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource(new StringSource("")); - Map<String, String> props = new HashMap<>(); + Properties props = new Properties(); props.put("key", "${env.testKey}"); - XmlNodeImpl configurationChild = new XmlNodeImpl("jdkHome", "${env.testKey}", null, null, null); - XmlNodeImpl configuration = - new XmlNodeImpl("configuration", null, null, Collections.singletonList(configurationChild), null); - ToolchainModel toolchain = ToolchainModel.newBuilder() - .type("TYPE") - .provides(props) - .configuration(configuration) - .build(); - PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder() - .toolchains(Collections.singletonList(toolchain)) - .build(); + Xpp3Dom configurationChild = new Xpp3Dom("jdkHome"); + configurationChild.setValue("${env.testKey}"); + Xpp3Dom configuration = new Xpp3Dom("configuration"); + configuration.addChild(configurationChild); + ToolchainModel toolchain = new ToolchainModel(); + toolchain.setType("TYPE"); + toolchain.setProvides(props); + toolchain.setConfiguration(configuration); + PersistedToolchains persistedToolchains = new PersistedToolchains(); + persistedToolchains.setToolchains(Collections.singletonList(toolchain)); doReturn(persistedToolchains) .when(toolchainsReader) @@ -274,13 +275,13 @@ public class DefaultToolchainsBuilderTest { ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource(new StringSource("")); - Map<String, String> props = new HashMap<>(); + Properties props = new Properties(); props.put("key", "${env.testNonExistingKey}"); - ToolchainModel toolchain = - ToolchainModel.newBuilder().type("TYPE").provides(props).build(); - PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder() - .toolchains(Collections.singletonList(toolchain)) - .build(); + ToolchainModel toolchain = new ToolchainModel(); + toolchain.setType("TYPE"); + toolchain.setProvides(props); + PersistedToolchains persistedToolchains = new PersistedToolchains(); + persistedToolchains.setToolchains(Collections.singletonList(toolchain)); doReturn(persistedToolchains) .when(toolchainsReader) @@ -303,13 +304,13 @@ public class DefaultToolchainsBuilderTest { ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource(new StringSource("")); - Map<String, String> props = new HashMap<>(); + Properties props = new Properties(); props.put("key", "${env.testSpecialCharactersKey}"); - ToolchainModel toolchain = - ToolchainModel.newBuilder().type("TYPE").provides(props).build(); - PersistedToolchains persistedToolchains = PersistedToolchains.newBuilder() - .toolchains(Collections.singletonList(toolchain)) - .build(); + ToolchainModel toolchain = new ToolchainModel(); + toolchain.setType("TYPE"); + toolchain.setProvides(props); + PersistedToolchains persistedToolchains = new PersistedToolchains(); + persistedToolchains.setToolchains(Collections.singletonList(toolchain)); doReturn(persistedToolchains) .when(toolchainsReader) diff --git a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java index b1d21217c..cab3d1593 100644 --- a/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java +++ b/maven-toolchain-builder/src/test/java/org/apache/maven/toolchain/merge/MavenToolchainMergerTest.java @@ -18,12 +18,14 @@ */ package org.apache.maven.toolchain.merge; +import java.io.IOException; import java.io.InputStream; +import java.util.Collections; -import org.apache.maven.api.toolchain.PersistedToolchains; -import org.apache.maven.api.toolchain.TrackableBase; -import org.apache.maven.api.xml.XmlNode; -import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; +import org.apache.maven.toolchain.io.DefaultToolchainsReader; +import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.toolchain.model.TrackableBase; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -31,95 +33,97 @@ import static org.junit.jupiter.api.Assertions.assertEquals; public class MavenToolchainMergerTest { private MavenToolchainMerger merger = new MavenToolchainMerger(); - private MavenToolchainsXpp3Reader reader = new MavenToolchainsXpp3Reader(); + private DefaultToolchainsReader reader = new DefaultToolchainsReader(); @Test public void testMergeNulls() { merger.merge(null, null, null); - PersistedToolchains pt = PersistedToolchains.newInstance(); + PersistedToolchains pt = new PersistedToolchains(); merger.merge(pt, null, null); merger.merge(null, pt, null); } @Test public void testMergeJdk() throws Exception { - try (InputStream isDominant = getClass().getResourceAsStream("toolchains-jdks.xml"); - InputStream isRecessive = getClass().getResourceAsStream("toolchains-jdks.xml")) { - PersistedToolchains dominant = reader.read(isDominant); - PersistedToolchains recessive = reader.read(isRecessive); + try (InputStream isDominant = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml"); + InputStream isRecessive = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml")) { + PersistedToolchains dominant = read(isDominant); + PersistedToolchains recessive = read(isRecessive); assertEquals(2, dominant.getToolchains().size()); - PersistedToolchains merged = merger.merge(dominant, recessive, TrackableBase.USER_LEVEL); - assertEquals(2, merged.getToolchains().size()); + merger.merge(dominant, recessive, TrackableBase.USER_LEVEL); + assertEquals(2, dominant.getToolchains().size()); } } @Test public void testMergeJdkExtra() throws Exception { - try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml"); - InputStream jdksExtraIS = getClass().getResourceAsStream("toolchains-jdks-extra.xml")) { - PersistedToolchains jdks = reader.read(jdksIS); - PersistedToolchains jdksExtra = reader.read(jdksExtraIS); + try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml"); + InputStream jdksExtraIS = + MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extra.xml")) { + PersistedToolchains jdks = read(jdksIS); + PersistedToolchains jdksExtra = read(jdksExtraIS); assertEquals(2, jdks.getToolchains().size()); - assertEquals(2, jdksExtra.getToolchains().size()); - PersistedToolchains merged = merger.merge(jdks, jdksExtra, TrackableBase.USER_LEVEL); - assertEquals(4, merged.getToolchains().size()); - assertEquals(2, jdks.getToolchains().size()); + merger.merge(jdks, jdksExtra, TrackableBase.USER_LEVEL); + assertEquals(4, jdks.getToolchains().size()); assertEquals(2, jdksExtra.getToolchains().size()); } - try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml"); - InputStream jdksExtraIS = getClass().getResourceAsStream("toolchains-jdks-extra.xml")) { - PersistedToolchains jdks = reader.read(jdksIS); - PersistedToolchains jdksExtra = reader.read(jdksExtraIS); + try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml"); + InputStream jdksExtraIS = + MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extra.xml")) { + PersistedToolchains jdks = read(jdksIS); + PersistedToolchains jdksExtra = read(jdksExtraIS); assertEquals(2, jdks.getToolchains().size()); - assertEquals(2, jdksExtra.getToolchains().size()); // switch dominant with recessive - PersistedToolchains merged = merger.merge(jdksExtra, jdks, TrackableBase.USER_LEVEL); - assertEquals(4, merged.getToolchains().size()); + merger.merge(jdksExtra, jdks, TrackableBase.USER_LEVEL); + assertEquals(4, jdksExtra.getToolchains().size()); assertEquals(2, jdks.getToolchains().size()); - assertEquals(2, jdksExtra.getToolchains().size()); } } @Test public void testMergeJdkExtend() throws Exception { - try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml"); - InputStream jdksExtendIS = getClass().getResourceAsStream("toolchains-jdks-extend.xml")) { - PersistedToolchains jdks = reader.read(jdksIS); - PersistedToolchains jdksExtend = reader.read(jdksExtendIS); + try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml"); + InputStream jdksExtendIS = + MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extend.xml")) { + PersistedToolchains jdks = read(jdksIS); + PersistedToolchains jdksExtend = read(jdksExtendIS); assertEquals(2, jdks.getToolchains().size()); - PersistedToolchains merged = merger.merge(jdks, jdksExtend, TrackableBase.USER_LEVEL); - assertEquals(2, merged.getToolchains().size()); - XmlNode config0 = merged.getToolchains().get(0).getConfiguration(); + merger.merge(jdks, jdksExtend, TrackableBase.USER_LEVEL); + assertEquals(2, jdks.getToolchains().size()); + Xpp3Dom config0 = (Xpp3Dom) jdks.getToolchains().get(0).getConfiguration(); assertEquals("lib/tools.jar", config0.getChild("toolsJar").getValue()); - assertEquals(2, config0.getChildren().size()); - XmlNode config1 = merged.getToolchains().get(1).getConfiguration(); - assertEquals(2, config1.getChildren().size()); + assertEquals(2, config0.getChildCount()); + Xpp3Dom config1 = (Xpp3Dom) jdks.getToolchains().get(1).getConfiguration(); + assertEquals(2, config1.getChildCount()); assertEquals("lib/classes.jar", config1.getChild("toolsJar").getValue()); - assertEquals(2, jdks.getToolchains().size()); assertEquals(2, jdksExtend.getToolchains().size()); } - try (InputStream jdksIS = getClass().getResourceAsStream("toolchains-jdks.xml"); - InputStream jdksExtendIS = getClass().getResourceAsStream("toolchains-jdks-extend.xml")) { - PersistedToolchains jdks = reader.read(jdksIS); - PersistedToolchains jdksExtend = reader.read(jdksExtendIS); + try (InputStream jdksIS = MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks.xml"); + InputStream jdksExtendIS = + MavenToolchainMergerTest.class.getResourceAsStream("toolchains-jdks-extend.xml")) { + PersistedToolchains jdks = read(jdksIS); + PersistedToolchains jdksExtend = read(jdksExtendIS); assertEquals(2, jdks.getToolchains().size()); // switch dominant with recessive - PersistedToolchains merged = merger.merge(jdksExtend, jdks, TrackableBase.USER_LEVEL); - assertEquals(2, merged.getToolchains().size()); - XmlNode config0 = merged.getToolchains().get(0).getConfiguration(); + merger.merge(jdksExtend, jdks, TrackableBase.USER_LEVEL); + assertEquals(2, jdksExtend.getToolchains().size()); + Xpp3Dom config0 = (Xpp3Dom) jdksExtend.getToolchains().get(0).getConfiguration(); assertEquals("lib/tools.jar", config0.getChild("toolsJar").getValue()); - assertEquals(2, config0.getChildren().size()); - XmlNode config1 = merged.getToolchains().get(1).getConfiguration(); - assertEquals(2, config1.getChildren().size()); + assertEquals(2, config0.getChildCount()); + Xpp3Dom config1 = (Xpp3Dom) jdksExtend.getToolchains().get(1).getConfiguration(); + assertEquals(2, config1.getChildCount()); assertEquals("lib/classes.jar", config1.getChild("toolsJar").getValue()); assertEquals(2, jdks.getToolchains().size()); - assertEquals(2, jdksExtend.getToolchains().size()); } } + + private PersistedToolchains read(InputStream is) throws IOException { + return reader.read(is, Collections.emptyMap()); + } } diff --git a/maven-toolchain-model/pom.xml b/maven-toolchain-model/pom.xml index ce241dbac..544b6e0ad 100644 --- a/maven-toolchain-model/pom.xml +++ b/maven-toolchain-model/pom.xml @@ -83,6 +83,28 @@ under the License. </execution> </executions> </plugin> + <plugin> + <groupId>com.github.siom79.japicmp</groupId> + <artifactId>japicmp-maven-plugin</artifactId> + <configuration> + <parameter> + <includes> + <include>org.apache.maven.toolchain.model</include> + </includes> + <excludes> + <exclude>org.apache.maven.toolchain.model.PersistedToolchains#setModelEncoding(java.lang.String):METHOD_REMOVED</exclude> + </excludes> + <includeExclusively>true</includeExclusively> + </parameter> + <oldVersion> + <dependency> + <groupId>org.apache.maven</groupId> + <artifactId>maven-core</artifactId> + <version>${maven.baseline}</version> + </dependency> + </oldVersion> + </configuration> + </plugin> </plugins> </build> diff --git a/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/BaseObject.java b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/BaseObject.java new file mode 100644 index 000000000..28bea64b8 --- /dev/null +++ b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/BaseObject.java @@ -0,0 +1,61 @@ +/* + * 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.toolchain.model; + +import java.io.Serializable; + +public abstract class BaseObject implements Serializable, Cloneable { + protected transient ChildrenTracking childrenTracking; + + protected Object delegate; + + public BaseObject() {} + + public BaseObject(Object delegate, BaseObject parent) { + this.delegate = delegate; + this.childrenTracking = parent != null ? parent::replace : null; + } + + public BaseObject(Object delegate, ChildrenTracking parent) { + this.delegate = delegate; + this.childrenTracking = parent; + } + + public Object getDelegate() { + return delegate; + } + + public void update(Object newDelegate) { + if (delegate != newDelegate) { + if (childrenTracking != null) { + childrenTracking.replace(delegate, newDelegate); + } + delegate = newDelegate; + } + } + + protected boolean replace(Object oldDelegate, Object newDelegate) { + return false; + } + + @FunctionalInterface + protected interface ChildrenTracking { + boolean replace(Object oldDelegate, Object newDelegate); + } +} diff --git a/pom.xml b/pom.xml index d471b8c62..d8f283a7b 100644 --- a/pom.xml +++ b/pom.xml @@ -170,6 +170,7 @@ under the License. <slf4jVersion>1.7.36</slf4jVersion> <xmlunitVersion>2.6.4</xmlunitVersion> <maven.test.redirectTestOutputToFile>true</maven.test.redirectTestOutputToFile> + <maven.baseline>3.8.7</maven.baseline> <!-- Control the name of the distribution and information output by mvn --> <distributionId>apache-maven</distributionId> <distributionShortName>Maven</distributionShortName> @@ -556,36 +557,11 @@ under the License. <configuration> <parameter> <!-- baseline is 3.8.6 for Maven 4 --> - <oldVersionPattern>3.8.6</oldVersionPattern> + <oldVersionPattern>${maven.baseline}</oldVersionPattern> <breakBuildOnBinaryIncompatibleModifications>true</breakBuildOnBinaryIncompatibleModifications> <onlyBinaryIncompatible>true</onlyBinaryIncompatible> - <!-- only exported packages from maven-core/META-INF/maven/extension.xml matter --> - <includes> - <include>org.apache.maven.artifact</include> - <include>org.apache.maven.classrealm</include> - <include>org.apache.maven.cli</include> - <include>org.apache.maven.configuration</include> - <include>org.apache.maven.exception</include> - <include>org.apache.maven.execution</include> - <include>org.apache.maven.execution.scope</include> - <include>org.apache.maven.feature</include> - <include>org.apache.maven.graph</include> - <include>org.apache.maven.lifecycle</include> - <include>org.apache.maven.model</include> - <include>org.apache.maven.monitor</include> - <include>org.apache.maven.plugin</include> - <include>org.apache.maven.profiles</include> - <include>org.apache.maven.project</include> - <include>org.apache.maven.reporting</include> - <include>org.apache.maven.repository</include> - <include>org.apache.maven.rtinfo</include> - <include>org.apache.maven.rtinfo.internal</include> - <include>org.apache.maven.settings</include> - <include>org.apache.maven.toolchain</include> - <include>org.apache.maven.usability</include> - </includes> - <includeExclusively>true</includeExclusively> <!-- don't include subpackages --> + <includeExclusively>true</includeExclusively> </parameter> </configuration> </execution> diff --git a/src/mdo/merger.vm b/src/mdo/merger.vm index ff4b81c19..1126d21d6 100644 --- a/src/mdo/merger.vm +++ b/src/mdo/merger.vm @@ -25,7 +25,8 @@ # #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; @@ -53,6 +54,16 @@ import ${packageModelV4}.${class.Name}; public class ${className} { + private final boolean deepMerge; + + public ${className}() { + this(true); + } + + public ${className}(boolean deepMerge) { + this.deepMerge = deepMerge; + } + /** * Merges the specified source object into the given target object. * @@ -169,7 +180,12 @@ public class ${className} } } #elseif ( $field.to && $field.multiplicity == "*" ) - builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + if (deepMerge) { + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), get${field.to}Key(), + ( t, s ) -> merge${field.to}( t, s, sourceDominant, context ) ) ); + } else { + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + } #elseif ( $field.type == "DOM" ) XmlNode src = source.getConfiguration(); if ( src != null ) diff --git a/src/mdo/model-v3-modified.vm b/src/mdo/model-v3-modified.vm deleted file mode 100644 index 0bb0f58b7..000000000 --- a/src/mdo/model-v3-modified.vm +++ /dev/null @@ -1,319 +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. -*# -#parse ( "common.vm" ) -# -#set ( $package = "${packageModelV3}" ) -# -#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) -# -#foreach ( $class in $model.allClasses ) - #set ( $ancestors = $Helper.ancestors( $class ) ) - #set ( $allFields = [] ) - #set ( $inheritedFields = [] ) - #foreach ( $cl in $ancestors ) - #if ( $cl != $class ) - #set ( $dummy = $inheritedFields.addAll( $cl.allFields ) ) - #end - #set ( $dummy = $allFields.addAll( $cl.allFields ) ) - #end - #set ( $className = "${class.name}" ) -#MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java - #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $types = { } ) - #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) - #set ( $dummy = $imports.add( "java.io.Serializable" ) ) - #set ( $dummy = $imports.add( "java.util.AbstractList" ) ) - #set ( $dummy = $imports.add( "java.util.Collections" ) ) - #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.Objects" ) ) - #set ( $dummy = $imports.add( "java.util.stream.Collectors" ) ) - #set ( $dummy = $imports.add( "java.util.stream.Stream" ) ) - #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) - #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) - #foreach ( $field in $allFields ) - #if ( $field.type == "java.util.List" ) - #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) - #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) - #elseif ( $field.type == "DOM" ) - #set ( $dummy = $imports.add( "org.codehaus.plexus.util.xml.Xpp3Dom" ) ) - #set ( $dummy = $types.put( $field, "Object" ) ) - #else - #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) - #set ( $idx = $fieldType.lastIndexOf('.') ) - #if ( $idx > 0 ) - #set ( $dummy = $imports.add( $fieldType ) ) - #set ( $dummy = $types.put( $fieldType, $fieldType.substring( $idx + 1 ) ) ) - #end - #end - #end - #set ( $eq = "" ) - #set ( $hc = "" ) - #foreach ( $field in $allFields ) - #if ( $field.identifier ) - #set ( $dummy = $imports.add( "java.util.Objects" ) ) - #set ( $dummy = $identifiers.add( $field ) ) - #if ( $eq == "" ) - #set ( $eq = "Objects.equals( this.${field.name}, that.${field.name} )" ) - #else - #set ( $eq = "$eq && Objects.equals( this.${field.name}, that.${field.name} )" ) - #end - #if ( $hc == "" ) - #set ( $hc = "${field.name}" ) - #else - #set ( $hc = "$hc, this.${field.name}" ) - #end - #end - #end -// =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. -// ============================================================== -package ${package}; - - #foreach ( $imp in $imports ) -import $imp; - #end - -@Generated -public class ${class.name} - #if ( $class.superClass ) - extends ${class.superClass} - implements Serializable, Cloneable - #else - extends BaseObject - #end -{ - - public ${class.name}() - { - this( ${packageModelV4}.${class.name}.newInstance() ); - } - - public ${class.name}( ${packageModelV4}.${class.name} delegate ) - { - this( delegate, null ); - } - - public ${class.name}( ${packageModelV4}.${class.name} delegate, BaseObject parent ) - { - super( delegate, parent ); - } - - public ${class.name} clone() - { - return new ${class.name}( getDelegate() ); - } - - #if ( $class.superClass ) - @Override - #end - public ${packageModelV4}.${class.name} getDelegate() - { - return ( ${packageModelV4}.${class.name} ) super.getDelegate(); - } - - #if ( ! $eq.empty ) - @Override - public boolean equals( Object o ) - { - if ( this == o ) - { - return true; - } - if ( o == null || !( o instanceof ${class.name} ) ) - { - return false; - } - ${class.name} that = ( ${class.name} ) o; - return Objects.equals( this.delegate, that.delegate ); - } - - @Override - public int hashCode() - { - return getDelegate().hashCode(); - } - - #end - #if ( $class == $root ) - public String getModelEncoding() - { - return getDelegate().getModelEncoding(); - } - - #end - #foreach ( $field in $class.getFields($version) ) - #set ( $cap = $Helper.capitalise( $field.name ) ) - #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) - #if ( $type == "boolean" || $type == "Boolean" ) - #set ( $pfx = "is" ) - #else - #set ( $pfx = "get" ) - #end - #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) - @Nonnull - #end - public ${type} ${pfx}${cap}() - { - #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>( - () -> getDelegate().get${cap}(), l -> update( getDelegate().with${cap}( l ) ), - d -> new ${field.to}( d, this ), ${field.to}::getDelegate ); - #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" ) - return new WrapperProperties( () -> getDelegate().get${cap}(), this::set${cap} ); - #elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - return new WrapperList<String, ${field.to}>( () -> getDelegate().get${cap}(), this::set${cap}, s -> s, s -> s ); - #elseif ( $field.to ) - return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}(), this ) : null; - #elseif ( $field.type == "DOM" ) - return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}(), this::replace ) : null; - #else - return getDelegate().${pfx}${cap}(); - #end - } - - public void set${cap}( ${type} ${field.name} ) - { - #if ( $field.type == "DOM" ) - if ( ! Objects.equals( ( ( Xpp3Dom ) ${field.name} ).getDom(), getDelegate().${pfx}${cap}() ) ) - { - update( getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ) ); - ( ( Xpp3Dom ) ${field.name} ).setChildrenTracking( this::replace ); - } - #elseif( $field.type == "java.util.Properties" ) - Map<String, String> map = ${field.name}.entrySet().stream() - .collect( Collectors.toMap( e -> e.getKey().toString(), e -> e.getValue().toString() ) ); - if ( !Objects.equals( map, getDelegate().get${cap}() ) ) - { - update( getDelegate().with${cap}( map ) ); - } - #else - if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) - { - #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - update( getDelegate().with${cap}( - ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ) ); - ${field.name}.forEach( e -> e.childrenTracking = this::replace ); - #elseif ( $field.to && $field.to != "String" ) - update( getDelegate().with${cap}( ${field.name}.getDelegate() ) ); - ${field.name}.childrenTracking = this::replace; - #else - update( getDelegate().with${cap}( ${field.name} ) ); - #end - } - #end - } - - #if ( $field.type == "java.util.List" && $field.multiplicity == "*" ) - #set ( $v = $Helper.singular( ${field.name} ) ) - #set ( $scap = $Helper.capitalise( $v ) ) - public void add${scap}( ${field.to} ${v} ) - { - #if ( $field.to == "String" ) - update( getDelegate().with${cap}( - Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) - .collect( Collectors.toList() ) ) ); - #else - update( getDelegate().with${cap}( - Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) - .collect( Collectors.toList() ) ) ); - ${v}.childrenTracking = this::replace; - #end - } - - public void remove${scap}( ${field.to} ${v} ) - { - #if ( $field.to == "String" ) - update( getDelegate().with${cap}( - getDelegate().get${cap}().stream() - .filter( e -> !Objects.equals( e, ${v} ) ) - .collect( Collectors.toList() ) ) ); - #else - update( getDelegate().with${cap}( - getDelegate().get${cap}().stream() - .filter( e -> !Objects.equals( e, ${v} ) ) - .collect( Collectors.toList() ) ) ); - ${v}.childrenTracking = null; - #end - } - - #end - #end - public InputLocation getLocation( Object key ) - { - ${packageModelV4}.InputLocation loc = getDelegate().getLocation( key ); - return loc != null ? new InputLocation( loc ) : null; - } - - public void setLocation( Object key, InputLocation location ) - { - update( ${packageModelV4}.${class.name}.newBuilder( getDelegate(), true ) - .location( key, location.toApiLocation() ).build() ); - } - - protected boolean replace( Object oldDelegate, Object newDelegate ) - { - if ( super.replace( oldDelegate, newDelegate ) ) - { - return true; - } - #foreach ( $field in $class.getFields($version) ) - #set ( $cap = $Helper.capitalise( $field.name ) ) - #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) - #if ( $field.to && $field.multiplicity != "*" ) - if ( oldDelegate == getDelegate().get${cap}() ) - { - update( getDelegate().with${cap}( ( ${packageModelV4}.${field.to} ) newDelegate ) ); - return true; - } - #elseif ( $field.type == "java.util.List" && $field.to != "String" ) - if ( getDelegate().get${cap}().contains( oldDelegate ) ) - { - List<${packageModelV4}.${field.to}> list = new ArrayList<>( getDelegate().get${cap}() ); - list.replaceAll( d -> d == oldDelegate ? ( ${packageModelV4}.${field.to} ) newDelegate : d ); - update( getDelegate().with${cap}( list ) ); - return true; - } - #elseif ( $field.type == "DOM" ) - if ( getDelegate().get${cap}() == oldDelegate ) - { - update( getDelegate().with${cap}( ( org.apache.maven.api.xml.XmlNode ) newDelegate ) ); - } - #end - #end - return false; - } - - public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) - { - return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; - } - - public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List<${packageModelV4}.${class.name}> list ) - { - return list != null ? new WrapperList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null; - } - - #foreach ( $cs in $class.getCodeSegments($version) ) -$cs.code - #end -} - #end -#end diff --git a/src/mdo/model-v3.vm b/src/mdo/model-v3.vm index 5eb69dd3a..70326dec5 100644 --- a/src/mdo/model-v3.vm +++ b/src/mdo/model-v3.vm @@ -43,6 +43,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.Objects" ) ) #set ( $dummy = $imports.add( "java.util.stream.Collectors" ) ) #set ( $dummy = $imports.add( "java.util.stream.Stream" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) @@ -82,7 +83,8 @@ #end #end // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; @@ -94,13 +96,11 @@ import $imp; public class ${class.name} #if ( $class.superClass ) extends ${class.superClass} - #end implements Serializable, Cloneable -{ - - #if ( ! $class.superClass ) - ${packageModelV4}.${class.name} delegate; + #else + extends BaseObject #end +{ public ${class.name}() { @@ -109,11 +109,12 @@ public class ${class.name} public ${class.name}( ${packageModelV4}.${class.name} delegate ) { - #if ( $class.superClass ) - super( delegate ); - #else - this.delegate = delegate; - #end + this( delegate, null ); + } + + public ${class.name}( ${packageModelV4}.${class.name} delegate, BaseObject parent ) + { + super( delegate, parent ); } public ${class.name} clone() @@ -126,14 +127,9 @@ public class ${class.name} #end public ${packageModelV4}.${class.name} getDelegate() { - #if ( $class.superClass ) - return ( ${packageModelV4}.${class.name} ) delegate; - #else - return delegate; - #end + return ( ${packageModelV4}.${class.name} ) super.getDelegate(); } - #if ( ! $eq.empty ) @Override public boolean equals( Object o ) { @@ -155,7 +151,6 @@ public class ${class.name} return getDelegate().hashCode(); } - #end #if ( $class == $root ) public String getModelEncoding() { @@ -178,16 +173,16 @@ public class ${class.name} { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>( - getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), - ${field.to}::new, ${field.to}::getDelegate ); + () -> getDelegate().get${cap}(), l -> update( getDelegate().with${cap}( l ) ), + d -> new ${field.to}( d, this ), ${field.to}::getDelegate ); #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" ) - return new WrapperProperties( getDelegate()::get${cap}, this::set${cap} ); + return new WrapperProperties( () -> getDelegate().get${cap}(), this::set${cap} ); #elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - return new WrapperList<String, ${field.to}>( getDelegate()::get${cap}, this::set${cap}, s -> s, s -> s ); + return new WrapperList<String, ${field.to}>( () -> getDelegate().get${cap}(), this::set${cap}, s -> s, s -> s ); #elseif ( $field.to ) - return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}() ) : null; + return getDelegate().${pfx}${cap}() != null ? new ${field.to}( getDelegate().${pfx}${cap}(), this ) : null; #elseif ( $field.type == "DOM" ) - return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}(), this::replace ) : null; #else return getDelegate().${pfx}${cap}(); #end @@ -196,18 +191,32 @@ public class ${class.name} public void set${cap}( ${type} ${field.name} ) { #if ( $field.type == "DOM" ) - delegate = getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ); + if ( ! Objects.equals( ( ( Xpp3Dom ) ${field.name} ).getDom(), getDelegate().${pfx}${cap}() ) ) + { + update( getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ) ); + ( ( Xpp3Dom ) ${field.name} ).setChildrenTracking( this::replace ); + } #elseif( $field.type == "java.util.Properties" ) Map<String, String> map = ${field.name}.entrySet().stream() .collect( Collectors.toMap( e -> e.getKey().toString(), e -> e.getValue().toString() ) ); - delegate = getDelegate().with${cap}( map ); - #elseif ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - delegate = getDelegate().with${cap}( - ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ); - #elseif ( $field.to && $field.to != "String" ) - delegate = getDelegate().with${cap}( ${field.name}.getDelegate() ); + if ( !Objects.equals( map, getDelegate().get${cap}() ) ) + { + update( getDelegate().with${cap}( map ) ); + } #else - delegate = getDelegate().with${cap}( ${field.name} ); + if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + update( getDelegate().with${cap}( + ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ) ); + ${field.name}.forEach( e -> e.childrenTracking = this::replace ); + #elseif ( $field.to && $field.to != "String" ) + update( getDelegate().with${cap}( ${field.name}.getDelegate() ) ); + ${field.name}.childrenTracking = this::replace; + #else + update( getDelegate().with${cap}( ${field.name} ) ); + #end + } #end } @@ -217,13 +226,30 @@ public class ${class.name} public void add${scap}( ${field.to} ${v} ) { #if ( $field.to == "String" ) - delegate = getDelegate().with${cap}( + update( getDelegate().with${cap}( Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) - .collect( Collectors.toList() ) ); + .collect( Collectors.toList() ) ) ); #else - delegate = getDelegate().with${cap}( + update( getDelegate().with${cap}( Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) - .collect( Collectors.toList() ) ); + .collect( Collectors.toList() ) ) ); + ${v}.childrenTracking = this::replace; + #end + } + + public void remove${scap}( ${field.to} ${v} ) + { + #if ( $field.to == "String" ) + update( getDelegate().with${cap}( + getDelegate().get${cap}().stream() + .filter( e -> !Objects.equals( e, ${v} ) ) + .collect( Collectors.toList() ) ) ); + #else + update( getDelegate().with${cap}( + getDelegate().get${cap}().stream() + .filter( e -> !Objects.equals( e, ${v} ) ) + .collect( Collectors.toList() ) ) ); + ${v}.childrenTracking = null; #end } @@ -237,6 +263,53 @@ public class ${class.name} #end #end + #if ( $locationTracking ) + public InputLocation getLocation( Object key ) + { + ${packageModelV4}.InputLocation loc = getDelegate().getLocation( key ); + return loc != null ? new InputLocation( loc ) : null; + } + + public void setLocation( Object key, InputLocation location ) + { + update( ${packageModelV4}.${class.name}.newBuilder( getDelegate(), true ) + .location( key, location.toApiLocation() ).build() ); + } + + #end + protected boolean replace( Object oldDelegate, Object newDelegate ) + { + if ( super.replace( oldDelegate, newDelegate ) ) + { + return true; + } + #foreach ( $field in $class.getFields($version) ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.to && $field.multiplicity != "*" ) + if ( oldDelegate == getDelegate().get${cap}() ) + { + update( getDelegate().with${cap}( ( ${packageModelV4}.${field.to} ) newDelegate ) ); + return true; + } + #elseif ( $field.type == "java.util.List" && $field.to != "String" ) + if ( getDelegate().get${cap}().contains( oldDelegate ) ) + { + List<${packageModelV4}.${field.to}> list = new ArrayList<>( getDelegate().get${cap}() ); + list.replaceAll( d -> d == oldDelegate ? ( ${packageModelV4}.${field.to} ) newDelegate : d ); + update( getDelegate().with${cap}( list ) ); + return true; + } + #elseif ( $field.type == "DOM" ) + if ( getDelegate().get${cap}() == oldDelegate ) + { + update( getDelegate().with${cap}( ( org.apache.maven.api.xml.XmlNode ) newDelegate ) ); + } + #end + #end + return false; + } + public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) { return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; diff --git a/src/mdo/model.vm b/src/mdo/model.vm index 4a8248ee8..54341e3d6 100644 --- a/src/mdo/model.vm +++ b/src/mdo/model.vm @@ -85,7 +85,8 @@ #end #end // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; diff --git a/src/mdo/reader-ex.vm b/src/mdo/reader-ex.vm index e92829538..a5b7c7e14 100644 --- a/src/mdo/reader-ex.vm +++ b/src/mdo/reader-ex.vm @@ -29,7 +29,8 @@ # #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; diff --git a/src/mdo/reader-modified.vm b/src/mdo/reader-modified.vm index 8787b8241..696cb1c91 100644 --- a/src/mdo/reader-modified.vm +++ b/src/mdo/reader-modified.vm @@ -29,7 +29,8 @@ # #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; diff --git a/src/mdo/reader.vm b/src/mdo/reader.vm index 390fec487..f43847aaf 100644 --- a/src/mdo/reader.vm +++ b/src/mdo/reader.vm @@ -29,7 +29,8 @@ # #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; diff --git a/src/mdo/transformer.vm b/src/mdo/transformer.vm index 34bc3f63b..75d602f3f 100644 --- a/src/mdo/transformer.vm +++ b/src/mdo/transformer.vm @@ -23,7 +23,8 @@ # #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; diff --git a/src/mdo/writer-ex.vm b/src/mdo/writer-ex.vm index 4698225d7..a204149c3 100644 --- a/src/mdo/writer-ex.vm +++ b/src/mdo/writer-ex.vm @@ -29,7 +29,8 @@ # #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package}; diff --git a/src/mdo/writer.vm b/src/mdo/writer.vm index aa754b73d..e968ec1a9 100644 --- a/src/mdo/writer.vm +++ b/src/mdo/writer.vm @@ -29,7 +29,8 @@ # #MODELLO-VELOCITY#SAVE-OUTPUT-TO ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== -// Generated by Modello Velocity from ${template} template, any modifications will be overwritten. +// Generated by Modello Velocity from ${template} +// template, any modifications will be overwritten. // ============================================================== package ${package};