From 03cfeb806356ca26f69d4f8e0dce183c4ddaeb93 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 30 Mar 2022 19:45:49 +0200 Subject: [PATCH 01/98] Fix build --- .../maven/settings/GlobalSettingsTest.java | 2 +- api/maven-api-core/pom.xml | 55 + .../java/org/apache/maven/api/Artifact.java | 113 + .../java/org/apache/maven/api/Dependency.java | 75 + .../main/java/org/apache/maven/api/Event.java | 95 + .../java/org/apache/maven/api/Exclusion.java | 32 + .../org/apache/maven/api/JavaToolchain.java | 27 + .../java/org/apache/maven/api/Listener.java | 32 + .../org/apache/maven/api/LocalRepository.java | 29 + .../java/org/apache/maven/api/Metadata.java | 41 + .../org/apache/maven/api/MojoExecution.java | 36 + .../main/java/org/apache/maven/api/Node.java | 90 + .../org/apache/maven/api/NodeVisitor.java | 52 + .../java/org/apache/maven/api/Project.java | 80 + .../apache/maven/api/RemoteRepository.java | 33 + .../java/org/apache/maven/api/Repository.java | 43 + .../apache/maven/api/RepositoryMetadata.java | 24 + .../java/org/apache/maven/api/Session.java | 337 ++ .../org/apache/maven/api/SessionData.java | 84 + .../java/org/apache/maven/api/Toolchain.java | 51 + .../org/apache/maven/api/plugin/Mojo.java | 45 + .../maven/api/plugin/MojoException.java | 94 + .../api/plugin/annotations/Component.java | 54 + .../maven/api/plugin/annotations/Execute.java | 62 + .../annotations/InstantiationStrategy.java | 46 + .../plugin/annotations/LifecyclePhase.java | 77 + .../maven/api/plugin/annotations/Mojo.java | 89 + .../api/plugin/annotations/Parameter.java | 92 + .../plugin/annotations/ResolutionScope.java | 76 + .../maven/api/services/ArtifactDeployer.java | 61 + .../services/ArtifactDeployerException.java | 44 + .../api/services/ArtifactDeployerRequest.java | 143 + .../maven/api/services/ArtifactFactory.java | 44 + .../services/ArtifactFactoryException.java | 36 + .../api/services/ArtifactFactoryRequest.java | 197 ++ .../maven/api/services/ArtifactInstaller.java | 71 + .../services/ArtifactInstallerException.java | 43 + .../services/ArtifactInstallerRequest.java | 103 + .../maven/api/services/ArtifactManager.java | 62 + .../maven/api/services/ArtifactResolver.java | 56 + .../services/ArtifactResolverException.java | 40 + .../api/services/ArtifactResolverRequest.java | 101 + .../api/services/ArtifactResolverResult.java | 37 + .../maven/api/services/BaseRequest.java | 66 + .../api/services/DependencyCollector.java | 115 + .../DependencyCollectorException.java | 42 + .../services/DependencyCollectorRequest.java | 288 ++ .../services/DependencyCollectorResult.java | 47 + .../maven/api/services/DependencyFactory.java | 37 + .../services/DependencyFactoryException.java | 36 + .../services/DependencyFactoryRequest.java | 167 + .../api/services/DependencyResolver.java | 90 + .../services/DependencyResolverException.java | 43 +- .../services/DependencyResolverRequest.java | 327 ++ .../services/DependencyResolverResult.java | 44 + .../api/services/LocalRepositoryManager.java | 41 + .../maven/api/services/MavenException.java | 47 + .../maven/api/services/ProjectBuilder.java | 57 + .../api/services/ProjectBuilderException.java | 37 + .../api/services/ProjectBuilderProblem.java | 101 + .../api/services/ProjectBuilderRequest.java | 218 ++ .../api/services/ProjectBuilderResult.java | 76 + .../api/services/ProjectBuilderSource.java | 30 + .../maven/api/services/ProjectManager.java | 93 + .../maven/api/services/RepositoryFactory.java | 37 + .../apache/maven/api/services/Service.java | 27 + .../maven/api/services/ToolchainFactory.java | 28 + .../maven/api/services/ToolchainManager.java | 41 + .../services/ToolchainManagerException.java | 37 + .../api/services/xml/ModelXmlFactory.java | 27 + .../api/services/xml/SettingsXmlFactory.java | 27 + .../services/xml/ToolchainsXmlFactory.java | 27 + .../maven/api/services/xml/XmlFactory.java | 72 + .../api/services/xml/XmlReaderException.java | 40 + .../api/services/xml/XmlReaderRequest.java | 222 ++ .../api/services/xml/XmlWriterException.java | 40 + .../api/services/xml/XmlWriterRequest.java | 100 + api/maven-api-meta/pom.xml | 32 + .../maven/api/annotations/Consumer.java | 42 + .../maven/api/annotations/Generated.java | 30 + .../maven/api/annotations/Immutable.java | 30 + .../apache/maven/api/annotations/Nonnull.java | 37 + .../maven/api/annotations/Nullable.java | 30 + .../maven/api/annotations/Provider.java | 42 + .../maven/api/annotations/ThreadSafe.java | 30 + api/maven-api-model/pom.xml | 101 + .../apache/maven/api/model/InputLocation.java | 201 ++ .../maven/api/model/InputLocationTracker.java | 26 + .../apache/maven/api/model/InputSource.java | 61 + .../apache/maven/api/model/ROProperties.java | 120 + .../apache/maven/api}/model/package-info.java | 2 +- .../maven-api-model}/src/main/mdo/maven.mdo | 326 +- api/maven-api-model/src/main/mdo/model.vm | 403 +++ api/maven-api-settings/pom.xml | 101 + .../maven/api/settings/ROProperties.java | 120 + api/maven-api-settings/src/main/mdo/model.vm | 331 ++ .../src/main/mdo/settings.mdo | 13 +- api/maven-api-settings/src/site/apt/index.apt | 36 + api/maven-api-settings/src/site/site.xml | 38 + api/maven-api-toolchain/pom.xml | 102 + .../maven/api/toolchain/ROProperties.java | 120 + api/maven-api-toolchain/src/main/mdo/model.vm | 332 ++ .../src/main/mdo/toolchains.mdo | 4 +- api/maven-api-xml/pom.xml | 40 + .../java/org/apache/maven/api/xml/Dom.java | 122 + api/modello-plugin-velocity/pom.xml | 94 + .../plugin/velocity/CachingOutputStream.java | 170 + .../plugin/velocity/CachingWriter.java | 62 + .../plugin/velocity/ModelloVelocityMojo.java | 110 + .../plugin/velocity/VelocityGenerator.java | 285 ++ .../resources/META-INF/plexus/components.xml | 31 + api/pom.xml | 43 + build/checkstyle-suppressions.xml | 1 - maven-bom/pom.xml | 5 + .../artifact/manager/DefaultWagonManager.java | 12 +- .../maven/profiles/DefaultProfileManager.java | 9 +- .../profiles/ProfilesConversionUtils.java | 2 +- .../org/apache/maven/project/ModelUtils.java | 302 +- .../DefaultModelInheritanceAssembler.java | 715 +---- .../validation/DefaultModelValidator.java | 2 +- .../legacy/LegacyRepositorySystem.java | 131 +- .../apache/maven/project/ModelUtilsTest.java | 637 ---- .../t12/ProjectInheritanceTest.java | 2 + .../LegacyRepositorySystemTest.java | 2 +- maven-core/pom.xml | 4 + .../java/org/apache/maven/DefaultMaven.java | 23 +- .../handler/DefaultArtifactHandler.java | 1 + .../maven/bridge/MavenRepositorySystem.java | 2 +- ...DefaultMavenExecutionRequestPopulator.java | 8 +- .../apache/maven/execution/MavenSession.java | 44 +- .../maven/execution/SettingsAdapter.java | 126 - ...DefaultRepositorySystemSessionFactory.java | 9 +- .../maven/internal/impl/DefaultArtifact.java | 132 + .../impl/DefaultArtifactDeployer.java | 76 + .../internal/impl/DefaultArtifactFactory.java | 60 + .../impl/DefaultArtifactInstaller.java | 107 + .../internal/impl/DefaultArtifactManager.java | 86 + .../impl/DefaultArtifactResolver.java | 73 + .../internal/impl/DefaultDependency.java | 96 + .../impl/DefaultDependencyCollector.java | 93 + .../impl/DefaultDependencyFactory.java | 56 + .../impl/DefaultDependencyResolver.java | 106 + .../internal/impl/DefaultLocalRepository.java | 67 + .../impl/DefaultLocalRepositoryManager.java | 81 + .../internal/impl/DefaultModelXmlFactory.java | 113 + .../maven/internal/impl/DefaultNode.java | 99 + .../maven/internal/impl/DefaultProject.java | 190 ++ .../internal/impl/DefaultProjectBuilder.java | 258 ++ .../internal/impl/DefaultProjectManager.java | 121 + .../impl/DefaultRemoteRepository.java | 67 + .../impl/DefaultRepositoryFactory.java | 88 + .../maven/internal/impl/DefaultSession.java | 525 +++ .../internal/impl/DefaultSessionFactory.java | 75 + .../impl/DefaultSettingsXmlFactory.java | 103 + .../impl/DefaultToolchainManager.java | 120 + .../impl/DefaultToolchainsXmlFactory.java | 103 + .../maven/internal/impl/MappedCollection.java | 63 + .../maven/internal/impl/MappedList.java | 48 + ...faultLifecycleExecutionPlanCalculator.java | 40 +- .../DefaultLifecyclePluginAnalyzer.java | 11 +- .../DefaultMojoExecutionConfigurator.java | 13 +- .../DefaultProjectArtifactFactory.java | 3 +- .../internal/MojoDescriptorCreator.java | 21 +- .../internal/builder/BuilderCommon.java | 6 +- .../lifecycle/mapping/LifecycleMojo.java | 8 +- .../DefaultLifecycleBindingsInjector.java | 70 +- .../CycleDetectedInPluginGraphException.java | 2 +- .../plugin/DefaultBuildPluginManager.java | 91 +- .../apache/maven/plugin/MojoExecution.java | 10 +- .../PluginParameterExpressionEvaluator.java | 37 +- .../internal/DefaultMavenPluginManager.java | 14 +- .../project/DefaultModelBuildingListener.java | 2 +- .../maven/project/DefaultProjectBuilder.java | 47 +- .../project/ExtensionDescriptorBuilder.java | 10 +- .../apache/maven/project/MavenProject.java | 19 +- .../maven/project/ProjectModelResolver.java | 32 +- .../apache/maven/project/ProjectSorter.java | 41 +- .../project/artifact/MavenMetadataSource.java | 6 +- .../project/artifact/ProjectArtifact.java | 4 +- .../scope/internal/SessionScopeModule.java | 2 + .../settings/DefaultMavenSettingsBuilder.java | 1 + .../maven/settings/MavenSettingsBuilder.java | 1 + .../apache/maven/settings/SettingsUtils.java | 246 +- .../maven/toolchain/DefaultToolchain.java | 2 +- .../toolchain/DefaultToolchainManager.java | 5 +- .../DefaultToolchainManagerPrivate.java | 8 +- .../toolchain/DefaultToolchainsBuilder.java | 4 +- .../maven/toolchain/ToolchainFactory.java | 2 +- .../maven/toolchain/ToolchainPrivate.java | 2 +- .../maven/toolchain/ToolchainsBuilder.java | 2 +- .../toolchain/java/DefaultJavaToolChain.java | 2 +- .../toolchain/java/JavaToolchainFactory.java | 8 +- .../toolchain/java/JavaToolchainImpl.java | 2 +- .../resources/META-INF/maven/extension.xml | 2 + .../AbstractCoreMavenComponentTestCase.java | 2 +- .../ConsumerModelSourceTransformerTest.java | 2 +- .../apache/maven/internal/impl/TestApi.java | 113 + .../internal/impl/TestArtifactHandler.java | 83 + .../internal/impl/TestRepositorySystem.java | 341 ++ .../lifecycle/LifecycleExecutorTest.java | 4 +- .../LifecycleExecutionPlanCalculatorStub.java | 2 +- .../maven/project/EmptyLifecycleExecutor.java | 2 +- .../project/ProjectModelResolverTest.java | 27 +- .../maven/project/ProjectSorterTest.java | 2 + .../CanonicalProjectBuilderTest.java | 5 +- .../harness/Xpp3DomAttributeIterator.java | 22 +- .../project/harness/Xpp3DomNodeIterator.java | 21 +- .../project/harness/Xpp3DomNodePointer.java | 23 +- .../harness/Xpp3DomPointerFactory.java | 10 +- .../repository/TestRepositorySystem.java | 5 +- .../PomConstructionWithSettingsTest.java | 2 +- .../maven/settings/SettingsUtilsTest.java | 100 +- .../DefaultToolchainManagerTest.java | 30 +- .../maven/toolchain/DefaultToolchainTest.java | 61 +- .../1.0.3/commons-logging-1.0.3.jar | Bin 0 -> 31605 bytes .../1.0.3/commons-logging-1.0.3.jar.sha1 | 1 + .../1.0.3/commons-logging-1.0.3.pom | 31 + .../1.0.3/commons-logging-1.0.3.pom.sha1 | 1 + ...ng-1.0.4-javadoc-resources.jar.lastUpdated | 4 + .../1.0.4/commons-logging-1.0.4.jar | Bin 0 -> 38015 bytes .../1.0.4/commons-logging-1.0.4.jar.sha1 | 1 + .../1.0.4/commons-logging-1.0.4.pom | 165 + .../1.0.4/commons-logging-1.0.4.pom.sha1 | 1 + .../org/apache/apache/3/apache-3.pom | 82 + .../org/apache/apache/3/apache-3.pom.md5 | 1 + .../org/apache/apache/3/apache-3.pom.sha1 | 1 + .../maven-artifact-3.0-SNAPSHOT.jar | Bin 0 -> 163984 bytes .../maven-artifact-3.0-SNAPSHOT.jar.md5 | 1 + .../maven-artifact-3.0-SNAPSHOT.jar.sha1 | 1 + .../maven-artifact-3.0-SNAPSHOT.pom | 112 + .../maven-artifact-3.0-SNAPSHOT.pom.md5 | 1 + .../maven-artifact-3.0-SNAPSHOT.pom.sha1 | 1 + .../test-extension/1/test-extension-1.jar | Bin 0 -> 4208 bytes .../test-extension/1/test-extension-1.pom | 73 + .../test-extension/1/test-extension-1.pom.md5 | 1 + .../1/test-extension-1.pom.sha1 | 1 + .../test-lifecycle-and-artifactHandler-1.jar | Bin 0 -> 2582 bytes .../test-lifecycle-and-artifactHandler-1.pom | 44 + ...st-lifecycle-and-artifactHandler-1.pom.md5 | 1 + ...t-lifecycle-and-artifactHandler-1.pom.sha1 | 1 + .../maven/maven-parent/4/maven-parent-4.pom | 304 ++ .../maven-parent/4/maven-parent-4.pom.md5 | 1 + .../maven-parent/4/maven-parent-4.pom.sha1 | 1 + .../maven/maven-parent/5/maven-parent-5.pom | 466 +++ .../maven-parent/5/maven-parent-5.pom.md5 | 1 + .../maven-parent/5/maven-parent-5.pom.sha1 | 1 + .../wagon-provider-api-1.0-beta-2.jar | Bin 0 -> 46326 bytes .../wagon-provider-api-1.0-beta-2.jar.md5 | 1 + .../wagon-provider-api-1.0-beta-2.jar.sha1 | 1 + .../wagon-provider-api-1.0-beta-2.pom | 21 + .../wagon-provider-api-1.0-beta-2.pom.md5 | 1 + .../wagon-provider-api-1.0-beta-2.pom.sha1 | 1 + .../1.0-beta-2/wagon-providers-1.0-beta-2.pom | 51 + .../wagon-providers-1.0-beta-2.pom.md5 | 1 + .../wagon-providers-1.0-beta-2.pom.sha1 | 1 + .../1.0-beta-2/wagon-webdav-1.0-beta-2.jar | Bin 0 -> 17297 bytes .../wagon-webdav-1.0-beta-2.jar.md5 | 1 + .../wagon-webdav-1.0-beta-2.jar.sha1 | 1 + .../1.0-beta-2/wagon-webdav-1.0-beta-2.pom | 50 + .../wagon-webdav-1.0-beta-2.pom.md5 | 1 + .../wagon-webdav-1.0-beta-2.pom.sha1 | 1 + .../wagon/1.0-beta-2/wagon-1.0-beta-2.pom | 170 + .../wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 | 1 + .../1.0-beta-2/wagon-1.0-beta-2.pom.sha1 | 1 + .../plexus-active-collections-1.0-beta-1.jar | Bin 0 -> 15961 bytes ...exus-active-collections-1.0-beta-1.jar.md5 | 1 + ...xus-active-collections-1.0-beta-1.jar.sha1 | 1 + .../plexus-active-collections-1.0-beta-1.pom | 51 + ...exus-active-collections-1.0-beta-1.pom.md5 | 1 + ...xus-active-collections-1.0-beta-1.pom.sha1 | 1 + .../plexus-classworlds-1.2-alpha-10.jar | Bin 0 -> 42472 bytes .../plexus-classworlds-1.2-alpha-10.jar.md5 | 1 + .../plexus-classworlds-1.2-alpha-10.jar.sha1 | 1 + .../plexus-classworlds-1.2-alpha-10.pom | 94 + .../plexus-classworlds-1.2-alpha-10.pom.md5 | 1 + .../plexus-classworlds-1.2-alpha-10.pom.sha1 | 1 + .../plexus-classworlds-1.2-alpha-7.jar | Bin 0 -> 42636 bytes .../plexus-classworlds-1.2-alpha-7.jar.md5 | 1 + .../plexus-classworlds-1.2-alpha-7.jar.sha1 | 1 + .../plexus-classworlds-1.2-alpha-7.pom | 78 + .../plexus-classworlds-1.2-alpha-7.pom.md5 | 1 + .../plexus-classworlds-1.2-alpha-7.pom.sha1 | 1 + .../plexus-component-api-1.0-alpha-16.jar | Bin 0 -> 33149 bytes .../plexus-component-api-1.0-alpha-16.jar.md5 | 1 + ...plexus-component-api-1.0-alpha-16.jar.sha1 | 1 + .../plexus-component-api-1.0-alpha-16.pom | 63 + .../plexus-component-api-1.0-alpha-16.pom.md5 | 1 + ...plexus-component-api-1.0-alpha-16.pom.sha1 | 1 + .../plexus-component-api-1.0-alpha-32.jar | Bin 0 -> 36108 bytes .../plexus-component-api-1.0-alpha-32.jar.md5 | 1 + ...plexus-component-api-1.0-alpha-32.jar.sha1 | 1 + .../plexus-component-api-1.0-alpha-32.pom | 61 + .../plexus-component-api-1.0-alpha-32.pom.md5 | 1 + ...plexus-component-api-1.0-alpha-32.pom.sha1 | 1 + .../1.1.6/plexus-components-1.1.6.pom | 60 + .../1.1.6/plexus-components-1.1.6.pom.md5 | 1 + .../1.1.6/plexus-components-1.1.6.pom.sha1 | 1 + .../plexus-container-default-1.0-alpha-16.jar | Bin 0 -> 210679 bytes ...xus-container-default-1.0-alpha-16.jar.md5 | 1 + ...us-container-default-1.0-alpha-16.jar.sha1 | 1 + .../plexus-container-default-1.0-alpha-16.pom | 56 + ...xus-container-default-1.0-alpha-16.pom.md5 | 1 + ...us-container-default-1.0-alpha-16.pom.sha1 | 1 + .../plexus-container-default-1.0-alpha-32.jar | Bin 0 -> 238880 bytes ...xus-container-default-1.0-alpha-32.jar.md5 | 1 + ...us-container-default-1.0-alpha-32.jar.sha1 | 1 + .../plexus-container-default-1.0-alpha-32.pom | 98 + ...xus-container-default-1.0-alpha-32.pom.md5 | 1 + ...us-container-default-1.0-alpha-32.pom.sha1 | 1 + .../plexus-containers-1.0-alpha-16.pom | 49 + .../plexus-containers-1.0-alpha-16.pom.md5 | 1 + .../plexus-containers-1.0-alpha-16.pom.sha1 | 1 + .../plexus-containers-1.0-alpha-32.pom | 49 + .../plexus-containers-1.0-alpha-32.pom.md5 | 1 + .../plexus-containers-1.0-alpha-32.pom.sha1 | 1 + .../plexus-utils/1.0.4/plexus-utils-1.0.4.jar | Bin 0 -> 163803 bytes .../1.0.4/plexus-utils-1.0.4.jar.sha1 | 1 + .../plexus-utils/1.0.4/plexus-utils-1.0.4.pom | 235 ++ .../1.0.4/plexus-utils-1.0.4.pom.sha1 | 1 + .../plexus-utils/1.1/plexus-utils-1.1.jar | Bin 0 -> 168568 bytes .../plexus-utils/1.1/plexus-utils-1.1.jar.md5 | 1 + .../1.1/plexus-utils-1.1.jar.sha1 | 1 + .../plexus-utils/1.1/plexus-utils-1.1.pom | 27 + .../plexus-utils/1.1/plexus-utils-1.1.pom.md5 | 1 + .../1.1/plexus-utils-1.1.pom.sha1 | 1 + .../plexus-utils/1.4.5/plexus-utils-1.4.5.jar | Bin 0 -> 205043 bytes .../1.4.5/plexus-utils-1.4.5.jar.md5 | 1 + .../1.4.5/plexus-utils-1.4.5.jar.sha1 | 1 + .../plexus-utils/1.4.5/plexus-utils-1.4.5.pom | 61 + .../1.4.5/plexus-utils-1.4.5.pom.md5 | 1 + .../1.4.5/plexus-utils-1.4.5.pom.sha1 | 1 + .../plexus/plexus/1.0.10/plexus-1.0.10.pom | 273 ++ .../plexus/1.0.10/plexus-1.0.10.pom.md5 | 1 + .../plexus/1.0.10/plexus-1.0.10.pom.sha1 | 1 + .../plexus/plexus/1.0.11/plexus-1.0.11.pom | 308 ++ .../plexus/1.0.11/plexus-1.0.11.pom.md5 | 1 + .../plexus/1.0.11/plexus-1.0.11.pom.sha1 | 1 + .../plexus/plexus/1.0.4/plexus-1.0.4.pom | 205 ++ .../plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 | 1 + .../plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 | 1 + .../plexus/plexus/1.0.8/plexus-1.0.8.pom | 259 ++ .../plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 | 1 + .../plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 | 1 + .../plexus/plexus/1.0.9/plexus-1.0.9.pom | 257 ++ .../plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 | 1 + .../plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 | 1 + ...core-1.3-javadoc-resources.jar.lastUpdated | 4 + .../1.3/hamcrest-core-1.3-javadoc.jar | Bin 0 -> 242519 bytes .../1.3/hamcrest-core-1.3-javadoc.jar.sha1 | 1 + .../1.3/hamcrest-core-1.3-sources.jar | Bin 0 -> 32624 bytes .../1.3/hamcrest-core-1.3-sources.jar.sha1 | 1 + .../hamcrest-core/1.3/hamcrest-core-1.3.jar | Bin 0 -> 45024 bytes .../1.3/hamcrest-core-1.3.jar.sha1 | 1 + .../hamcrest-core/1.3/hamcrest-core-1.3.pom | 18 + .../1.3/hamcrest-core-1.3.pom.sha1 | 1 + .../1.3/hamcrest-parent-1.3.pom | 72 + .../1.3/hamcrest-parent-1.3.pom.sha1 | 1 + .../java/org/apache/maven/cli/MavenCli.java | 3 +- .../SettingsXmlConfigurationProcessor.java | 32 +- .../BootstrapCoreExtensionManager.java | 14 +- .../DefaultBuildPomXMLFilterFactory.java | 2 +- .../model/building/DefaultModelBuilder.java | 248 +- .../building/DefaultModelBuilderFactory.java | 7 +- .../building/DefaultModelBuildingEvent.java | 2 +- .../building/DefaultModelBuildingRequest.java | 4 +- .../building/DefaultModelBuildingResult.java | 4 +- .../model/building/DefaultModelProblem.java | 2 +- .../DefaultModelProblemCollector.java | 2 +- .../model/building/DefaultModelProcessor.java | 2 +- .../building/DefaultTransformerContext.java | 2 +- .../model/building/FileToRawModelMerger.java | 85 +- .../building/FilterModelBuildingRequest.java | 4 +- .../maven/model/building/ModelBuilder.java | 2 +- .../model/building/ModelBuildingEvent.java | 2 +- .../building/ModelBuildingException.java | 2 +- .../model/building/ModelBuildingRequest.java | 4 +- .../model/building/ModelBuildingResult.java | 4 +- .../maven/model/building/ModelCacheTag.java | 17 +- .../maven/model/building/ModelData.java | 2 +- .../ModelProblemCollectorRequest.java | 2 +- .../model/building/ModelProblemUtils.java | 10 +- .../model/building/TransformerContext.java | 2 +- .../DefaultDependencyManagementImporter.java | 20 +- .../DependencyManagementImporter.java | 6 +- .../DefaultInheritanceAssembler.java | 77 +- .../inheritance/InheritanceAssembler.java | 4 +- .../AbstractStringBasedModelInterpolator.java | 2 +- .../interpolation/ModelInterpolator.java | 2 +- .../StringSearchModelInterpolator.java | 527 ---- .../StringVisitorModelInterpolator.java | 1352 +------- .../maven/model/io/DefaultModelReader.java | 59 +- .../maven/model/io/DefaultModelWriter.java | 4 +- .../apache/maven/model/io/ModelReader.java | 5 +- .../apache/maven/model/io/ModelWriter.java | 2 +- .../DefaultDependencyManagementInjector.java | 49 +- .../DefaultPluginManagementInjector.java | 43 +- .../DependencyManagementInjector.java | 4 +- .../management/PluginManagementInjector.java | 4 +- .../maven/model/merge/MavenModelMerger.java | 277 +- .../normalization/DefaultModelNormalizer.java | 77 +- .../model/normalization/ModelNormalizer.java | 6 +- .../path/DefaultModelPathTranslator.java | 102 +- .../model/path/DefaultModelUrlNormalizer.java | 43 +- .../maven/model/path/ModelPathTranslator.java | 4 +- .../maven/model/path/ModelUrlNormalizer.java | 4 +- ...ProfileActivationFilePathInterpolator.java | 2 +- .../DefaultPluginConfigurationExpander.java | 56 +- .../DefaultReportConfigurationExpander.java | 33 +- .../plugin/DefaultReportingConverter.java | 183 +- .../plugin/LifecycleBindingsInjector.java | 4 +- .../plugin/PluginConfigurationExpander.java | 4 +- .../plugin/ReportConfigurationExpander.java | 4 +- .../model/plugin/ReportingConverter.java | 4 +- .../model/profile/DefaultProfileInjector.java | 105 +- .../model/profile/DefaultProfileSelector.java | 4 +- .../maven/model/profile/ProfileInjector.java | 6 +- .../maven/model/profile/ProfileSelector.java | 2 +- .../activation/FileProfileActivator.java | 6 +- .../JdkVersionProfileActivator.java | 4 +- .../OperatingSystemProfileActivator.java | 6 +- .../profile/activation/ProfileActivator.java | 2 +- .../activation/PropertyProfileActivator.java | 6 +- .../InvalidRepositoryException.java | 2 +- .../maven/model/resolution/ModelResolver.java | 12 +- .../resolution/WorkspaceModelResolver.java | 2 +- .../superpom/DefaultSuperPomProvider.java | 9 +- .../model/superpom/SuperPomProvider.java | 2 +- .../validation/DefaultModelValidator.java | 60 +- .../model/validation/ModelValidator.java | 2 +- .../DefaultModelBuilderFactoryTest.java | 9 +- .../building/DefaultModelBuilderTest.java | 17 +- .../building/FileToRawModelMergerTest.java | 2 +- .../building/SimpleProblemCollector.java | 2 +- .../DefaultInheritanceAssemblerTest.java | 14 +- .../AbstractModelInterpolatorTest.java | 182 +- .../StringSearchModelInterpolatorTest.java | 618 ---- .../model/merge/MavenModelMergerTest.java | 78 +- .../AbstractProfileActivatorTest.java | 2 +- .../activation/FileProfileActivatorTest.java | 24 +- .../JdkVersionProfileActivatorTest.java | 14 +- .../PropertyProfileActivatorTest.java | 23 +- .../validation/DefaultModelValidatorTest.java | 4 +- maven-model/pom.xml | 80 +- .../org/apache/maven/model/InputLocation.java | 428 +++ .../maven/model/InputLocationTracker.java | 54 + .../org/apache/maven/model/InputSource.java | 150 + .../org/apache/maven/model/MappingList.java | 75 + .../org/apache/maven/model/WrapperList.java | 129 + .../apache/maven/model/WrapperProperties.java | 356 +++ .../maven/model/io/xpp3/MavenXpp3Reader.java | 166 + .../model/io/xpp3/MavenXpp3ReaderEx.java | 169 + .../maven/model/io/xpp3/MavenXpp3Writer.java | 83 + .../model/io/xpp3/MavenXpp3WriterEx.java | 83 + .../apache/maven/model/merge/ModelMerger.java | 2802 ----------------- maven-model/src/main/mdo/merger.vm | 354 +++ maven-model/src/main/mdo/model-v3.vm | 247 ++ maven-model/src/main/mdo/reader-ex.vm | 827 +++++ maven-model/src/main/mdo/reader.vm | 848 +++++ maven-model/src/main/mdo/transformer.vm | 154 + maven-model/src/main/mdo/writer-ex.vm | 32 + maven-model/src/main/mdo/writer.vm | 304 ++ .../maven/model/merge/ModelMergerTest.java | 72 +- maven-plugin-api/pom.xml | 35 + .../plugin/descriptor/MojoDescriptor.java | 14 +- .../descriptor/PluginDescriptorBuilder.java | 13 +- maven-plugin-api/src/main/mdo/merger.vm | 358 +++ maven-plugin-api/src/main/mdo/model.vm | 331 ++ maven-plugin-api/src/main/mdo/reader.vm | 901 ++++++ maven-plugin-api/src/main/mdo/writer.vm | 325 ++ maven-resolver-provider/pom.xml | 9 + .../internal/ArtifactDescriptorUtils.java | 1 + .../DefaultArtifactDescriptorReader.java | 2 +- .../internal/DefaultModelResolver.java | 30 +- .../internal/PluginsMetadataInfoProvider.java | 3 + .../internal/RelocatedArtifact.java | 1 + .../internal/DefaultModelResolverTest.java | 117 +- .../building/DefaultSettingsBuilder.java | 14 +- .../DefaultSettingsBuildingResult.java | 2 +- .../building/SettingsBuildingResult.java | 2 +- .../crypto/DefaultSettingsDecrypter.java | 22 +- .../DefaultSettingsDecryptionRequest.java | 6 +- .../DefaultSettingsDecryptionResult.java | 4 +- .../crypto/SettingsDecryptionRequest.java | 4 +- .../crypto/SettingsDecryptionResult.java | 4 +- .../settings/io/DefaultSettingsReader.java | 4 +- .../settings/io/DefaultSettingsWriter.java | 4 +- .../maven/settings/io/SettingsReader.java | 2 +- .../maven/settings/io/SettingsWriter.java | 2 +- .../settings/merge/MavenSettingsMerger.java | 80 +- .../validation/DefaultSettingsValidator.java | 12 +- .../validation/SettingsValidator.java | 2 +- .../DefaultSettingsValidatorTest.java | 128 +- maven-settings/pom.xml | 68 +- .../apache/maven/settings/WrapperList.java | 129 + .../maven/settings/WrapperProperties.java | 356 +++ .../settings/io/xpp3/SettingsXpp3Reader.java | 167 + .../settings/io/xpp3/SettingsXpp3Writer.java | 84 + maven-settings/src/main/mdo/merger.vm | 358 +++ maven-settings/src/main/mdo/model-v3.vm | 236 ++ maven-settings/src/main/mdo/reader.vm | 901 ++++++ maven-settings/src/main/mdo/writer.vm | 325 ++ .../building/DefaultToolchainsBuilder.java | 17 +- .../DefaultToolchainsBuildingResult.java | 2 +- .../building/ToolchainsBuildingResult.java | 2 +- .../toolchain/io/DefaultToolchainsReader.java | 4 +- .../toolchain/io/DefaultToolchainsWriter.java | 4 +- .../maven/toolchain/io/ToolchainsReader.java | 2 +- .../maven/toolchain/io/ToolchainsWriter.java | 2 +- .../toolchain/merge/MavenToolchainMerger.java | 45 +- .../DefaultToolchainsBuilderTest.java | 119 +- .../merge/MavenToolchainMergerTest.java | 74 +- .../toolchains-jdks-extend.xml | 0 .../toolchains-jdks-extra.xml | 0 .../{model => merge}/toolchains-jdks.xml | 0 maven-toolchain-model/pom.xml | 68 +- .../maven/toolchain/model/WrapperList.java | 129 + .../toolchain/model/WrapperProperties.java | 356 +++ maven-toolchain-model/src/main/mdo/merger.vm | 358 +++ .../src/main/mdo/model-v3.vm | 236 ++ maven-toolchain-model/src/main/mdo/reader.vm | 901 ++++++ maven-toolchain-model/src/main/mdo/writer.vm | 325 ++ maven-xml-impl/pom.xml | 58 + .../apache/maven/internal/xml/DomBuilder.java | 93 + .../maven/internal/xml/MavenXmlException.java | 47 + .../internal/xml/XmlPlexusConfiguration.java | 35 + .../apache/maven/internal/xml/Xpp3Dom.java | 465 +++ .../maven/internal/xml/Xpp3DomBuilder.java | 215 ++ .../maven/internal/xml/Xpp3DomWriter.java | 79 + pom.xml | 5 +- 529 files changed, 31545 insertions(+), 9321 deletions(-) create mode 100644 api/maven-api-core/pom.xml create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Event.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Node.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Project.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Session.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java rename maven-settings/src/main/java/org/apache/maven/settings/RuntimeInfo.java => api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java (52%) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/Service.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java create mode 100644 api/maven-api-meta/pom.xml create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java create mode 100644 api/maven-api-model/pom.xml create mode 100644 api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java create mode 100644 api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java create mode 100644 api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java create mode 100644 api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java rename {maven-model/src/main/java/org/apache/maven => api/maven-api-model/src/main/java/org/apache/maven/api}/model/package-info.java (96%) rename {maven-model => api/maven-api-model}/src/main/mdo/maven.mdo (93%) create mode 100644 api/maven-api-model/src/main/mdo/model.vm create mode 100644 api/maven-api-settings/pom.xml create mode 100644 api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java create mode 100644 api/maven-api-settings/src/main/mdo/model.vm rename {maven-settings => api/maven-api-settings}/src/main/mdo/settings.mdo (99%) create mode 100644 api/maven-api-settings/src/site/apt/index.apt create mode 100644 api/maven-api-settings/src/site/site.xml create mode 100644 api/maven-api-toolchain/pom.xml create mode 100644 api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java create mode 100644 api/maven-api-toolchain/src/main/mdo/model.vm rename {maven-toolchain-model => api/maven-api-toolchain}/src/main/mdo/toolchains.mdo (98%) create mode 100644 api/maven-api-xml/pom.xml create mode 100644 api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java create mode 100644 api/modello-plugin-velocity/pom.xml create mode 100644 api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingOutputStream.java create mode 100644 api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingWriter.java create mode 100644 api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java create mode 100644 api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java create mode 100644 api/modello-plugin-velocity/src/main/resources/META-INF/plexus/components.xml create mode 100644 api/pom.xml delete mode 100644 maven-compat/src/test/java/org/apache/maven/project/ModelUtilsTest.java delete mode 100644 maven-core/src/main/java/org/apache/maven/execution/SettingsAdapter.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepositoryManager.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRemoteRepository.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/MappedCollection.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/MappedList.java create mode 100644 maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java create mode 100644 maven-core/src/test/java/org/apache/maven/internal/impl/TestArtifactHandler.java create mode 100644 maven-core/src/test/java/org/apache/maven/internal/impl/TestRepositorySystem.java create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4-javadoc-resources.jar.lastUpdated create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc-resources.jar.lastUpdated create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom.sha1 create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom create mode 100644 maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom.sha1 delete mode 100644 maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java delete mode 100644 maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/InputLocation.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/InputLocationTracker.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/InputSource.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/MappingList.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/WrapperList.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Reader.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3ReaderEx.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Writer.java create mode 100644 maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java delete mode 100644 maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java create mode 100644 maven-model/src/main/mdo/merger.vm create mode 100644 maven-model/src/main/mdo/model-v3.vm create mode 100644 maven-model/src/main/mdo/reader-ex.vm create mode 100644 maven-model/src/main/mdo/reader.vm create mode 100644 maven-model/src/main/mdo/transformer.vm create mode 100644 maven-model/src/main/mdo/writer-ex.vm create mode 100644 maven-model/src/main/mdo/writer.vm create mode 100644 maven-plugin-api/src/main/mdo/merger.vm create mode 100644 maven-plugin-api/src/main/mdo/model.vm create mode 100644 maven-plugin-api/src/main/mdo/reader.vm create mode 100644 maven-plugin-api/src/main/mdo/writer.vm create mode 100644 maven-settings/src/main/java/org/apache/maven/settings/WrapperList.java create mode 100644 maven-settings/src/main/java/org/apache/maven/settings/WrapperProperties.java create mode 100644 maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Reader.java create mode 100644 maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Writer.java create mode 100644 maven-settings/src/main/mdo/merger.vm create mode 100644 maven-settings/src/main/mdo/model-v3.vm create mode 100644 maven-settings/src/main/mdo/reader.vm create mode 100644 maven-settings/src/main/mdo/writer.vm rename maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/{model => merge}/toolchains-jdks-extend.xml (100%) rename maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/{model => merge}/toolchains-jdks-extra.xml (100%) rename maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/{model => merge}/toolchains-jdks.xml (100%) create mode 100644 maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperList.java create mode 100644 maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperProperties.java create mode 100644 maven-toolchain-model/src/main/mdo/merger.vm create mode 100644 maven-toolchain-model/src/main/mdo/model-v3.vm create mode 100644 maven-toolchain-model/src/main/mdo/reader.vm create mode 100644 maven-toolchain-model/src/main/mdo/writer.vm create mode 100644 maven-xml-impl/pom.xml create mode 100644 maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java create mode 100644 maven-xml-impl/src/main/java/org/apache/maven/internal/xml/MavenXmlException.java create mode 100644 maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java create mode 100644 maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java create mode 100644 maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomBuilder.java create mode 100644 maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomWriter.java diff --git a/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java b/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java index 70a11151fe53..7d1853b7a703 100644 --- a/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java +++ b/apache-maven/src/test/java/org/apache/maven/settings/GlobalSettingsTest.java @@ -25,7 +25,7 @@ import java.io.Reader; import java.nio.charset.StandardCharsets; -import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader; +import org.apache.maven.settings.v4.SettingsXpp3Reader; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; diff --git a/api/maven-api-core/pom.xml b/api/maven-api-core/pom.xml new file mode 100644 index 000000000000..6ffef24727fc --- /dev/null +++ b/api/maven-api-core/pom.xml @@ -0,0 +1,55 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-core + Apache Maven Core API + + + + org.apache.maven + maven-api-meta + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-api-model + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-api-settings + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-api-toolchain + 4.0.0-alpha-1-SNAPSHOT + + + + diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java new file mode 100644 index 000000000000..98ed400cbb1c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -0,0 +1,113 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Immutable; + +import java.nio.file.Path; +import java.util.Optional; + +/** + * TODO: split between Coordinates / AttachedArtifact / ResolvedArtifact + */ +@Immutable +public interface Artifact +{ + + /** + * The groupId of the artifact. + * + * @return The groupId. + */ + @Nonnull + String getGroupId(); + + /** + * The artifactId of the artifact. + * + * @return The artifactId. + */ + @Nonnull + String getArtifactId(); + + /** + * The classifier of the artifact. + * + * @return The classifier or an empty string if none, never {@code null}. + */ + @Nonnull + String getClassifier(); + + /** + * The version of the artifact. + * + * @return The version. + */ + @Nonnull + String getVersion(); + + /** + * The file extension of the artifact. + * + * @return The extension. + */ + @Nonnull + String getExtension(); + + /** + * Gets the base version of this artifact, for example "1.0-SNAPSHOT". In contrast to the {@link #getVersion()}, the + * base version will always refer to the unresolved version. + * + * @return The base version, never {@code null}. + */ + @Nonnull + String getBaseVersion(); + + /** + * Determines whether this artifact uses a snapshot version. + * + * @return {@code true} if the artifact is a snapshot, {@code false} otherwise. + * @see org.apache.maven.api.Session#isVersionSnapshot(String) + */ + boolean isSnapshot(); + + /** + * Gets the file of this artifact. Note that only resolved artifacts have a file associated with them. In general, + * callers must not assume any relationship between an artifact's filename and its coordinates. + * + * @return The file or {@link Optional#empty()} if the artifact isn't resolved. + */ + @Nonnull + Optional getPath(); + + /** + * Unique id identifying this artifact + */ + default String getId() + { + return getGroupId() + + ":" + getArtifactId() + + ":" + getExtension() + + ( getClassifier().isEmpty() ? "" : ":" + getClassifier() ) + + ":" + getBaseVersion(); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java new file mode 100644 index 000000000000..ea208bfcfbdc --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -0,0 +1,75 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.Immutable; + +import java.util.Collection; + +@Immutable +public interface Dependency +{ + @Nonnull + Artifact getArtifact(); + + // TODO: make that en enum ? + @Nonnull + String getScope(); + + @Nullable + Boolean getOptional(); + + @Nonnull + Collection getExclusions(); + + @Nonnull + default String getGroupId() + { + return getArtifact().getGroupId(); + } + + @Nonnull + default String getArtifactId() + { + return getArtifact().getArtifactId(); + } + + @Nonnull + default String getVersion() + { + return getArtifact().getVersion(); + } + + @Nonnull + default String getType() + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Nonnull + default String getClassifier() + { + return getArtifact().getClassifier(); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java new file mode 100644 index 000000000000..37da3d5765b8 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java @@ -0,0 +1,95 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.Optional; + +/** + * Event + */ +public interface Event +{ + + /** + * The possible types of execution events. + */ + enum Type + { + ProjectDiscoveryStarted, + SessionStarted, + SessionEnded, + ProjectSkipped, + ProjectStarted, + ProjectSucceeded, + ProjectFailed, + MojoSkipped, + MojoStarted, + MojoSucceeded, + MojoFailed, + ForkStarted, + ForkSucceeded, + ForkFailed, + ForkedProjectStarted, + ForkedProjectSucceeded, + ForkedProjectFailed, + } + + /** + * Gets the type of the event. + * + * @return The type of the event, never {@code null}. + */ + @Nonnull + Type getType(); + + /** + * Gets the session from which this event originates. + * + * @return The current session, never {@code null}. + */ + @Nonnull + Session getSession(); + + /** + * Gets the current project (if any). + * + * @return The current project or {@code empty()} if not applicable. + */ + @Nonnull + Optional getProject(); + + /** + * Gets the current mojo execution (if any). + * + * @return The current mojo execution or {@code empty()} if not applicable. + */ + @Nonnull + Optional getMojoExecution(); + + /** + * Gets the exception that caused the event (if any). + * + * @return The exception or {@code empty()} if none. + */ + Optional getException(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java new file mode 100644 index 000000000000..11922c4f0802 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java @@ -0,0 +1,32 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nullable; + +public interface Exclusion +{ + @Nullable + String getGroupId(); + + @Nullable + String getArtifactId(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java new file mode 100644 index 000000000000..d863e6f81b09 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java @@ -0,0 +1,27 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +public interface JavaToolchain extends Toolchain +{ + + String getJavaHome(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java new file mode 100644 index 000000000000..d2c462339a57 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java @@ -0,0 +1,32 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A listener for session events. + */ +@FunctionalInterface @Consumer +public interface Listener +{ + void onEvent( @Nonnull Event event ); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java new file mode 100644 index 000000000000..d1135673dcb0 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java @@ -0,0 +1,29 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.nio.file.Path; + +public interface LocalRepository extends Repository +{ + + Path getPath(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java new file mode 100644 index 000000000000..d0b83eff15a8 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java @@ -0,0 +1,41 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +/** + * TODO: investigate removing the Metadata api completely + */ +public interface Metadata +{ + + String getGroupId(); + + String getArtifactId(); + + String getVersion(); + + enum Storage + { + Group, Artifact, Version + } + + Storage getStorage(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java new file mode 100644 index 000000000000..db526a7a4488 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java @@ -0,0 +1,36 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.model.Plugin; + +public interface MojoExecution +{ + @Nonnull + Plugin getPlugin(); + + @Nonnull + String getExecutionId(); + + @Nonnull + String getGoal(); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java new file mode 100644 index 000000000000..3c4ae402f0b0 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java @@ -0,0 +1,90 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Immutable; + +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; +import java.util.stream.Stream; + +/** + * Represents a dependency node within a Maven project's dependency collector. + */ +@Immutable +public interface Node +{ + /** + * @return artifact for this node + */ + Artifact getArtifact(); + + /** + * @return dependency for this node + */ + Dependency getDependency(); + + /** + * Gets the child nodes of this node. + * + * @return the child nodes of this node, never {@code null} + */ + List getChildren(); + + /** + * @return repositories of this node + */ + List getRemoteRepositories(); + + /** + * The repository where this artifact has been downloaded from. + */ + Optional getRepository(); + + /** + * Traverses this node and potentially its children using the specified visitor. + * + * @param visitor The visitor to call back, must not be {@code null}. + * @return {@code true} to visit siblings nodes of this node as well, {@code false} to skip siblings. + */ + boolean accept( NodeVisitor visitor ); + + /** + * Returns a new tree starting at this node, filtering the children. + * Note that this node will not be filtered and only the children + * and its descendant will be checked. + * + * @param filter the filter to apply + * @return a new filtered graph + */ + Node filter( Predicate filter ); + + /** + * Obtain a Stream containing this node and all its descendant. + * + * @return a stream containing this node and its descendant + */ + default Stream stream() + { + return Stream.concat( Stream.of( this ), getChildren().stream().flatMap( Node::stream ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java new file mode 100644 index 000000000000..9771748797f4 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java @@ -0,0 +1,52 @@ +package org.apache.maven.api; + +/* + * 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. + */ + + +import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Defines a hierarchical visitor for collecting dependency node trees. + * + * @author Pim Moerenhout + * @since 0.12 + */ +@Consumer +public interface NodeVisitor +{ + /** + * Starts the visit to the specified dependency node. + * + * @param node the dependency node to visit + * @return true to visit the specified dependency node's children, false to skip the + * specified dependency node's children and proceed to its next sibling + */ + boolean enter( @Nonnull Node node ); + + /** + * Ends the visit to the specified dependency node. + * + * @param node the dependency node to visit + * @return true to visit the specified dependency node's next sibling, false to skip the + * specified dependency node's next siblings and proceed to its parent + */ + boolean leave( @Nonnull Node node ); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java new file mode 100644 index 000000000000..80352c8a3c31 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -0,0 +1,80 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.List; + +import org.apache.maven.api.model.Model; + +/** + * Interface representing a Maven project. + */ +public interface Project +{ + + @Nonnull + String getGroupId(); + + @Nonnull + String getArtifactId(); + + @Nonnull + String getVersion(); + + @Nonnull + String getPackaging(); + + @Nonnull + Artifact getArtifact(); + + @Nonnull + Model getModel(); + + /** + * Returns the path to the pom file for this project. + * A project is usually read from the file system and this will point to + * the file. In some cases, a transient project can be created which + * will not point to an actual pom file. + * @return the path of the pom + */ + Path getPomPath(); + + default Path getBasedir() + { + Path pomPath = getPomPath(); + return pomPath != null ? pomPath.getParent() : null; + } + + @Nonnull + List getDependencies(); + + @Nonnull + List getManagedDependencies(); + + default String getId() + { + return getModel().getId(); + } + + boolean isExecutionRoot(); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java new file mode 100644 index 000000000000..399c6d8c7527 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java @@ -0,0 +1,33 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +public interface RemoteRepository extends Repository +{ + + @Nonnull + String getUrl(); + + @Nonnull + String getProtocol(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java new file mode 100644 index 000000000000..2f2d651199ed --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java @@ -0,0 +1,43 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +public interface Repository +{ + + /** + * Gets the identifier of this repository. + * + * @return The (case-sensitive) identifier, never {@code null}. + */ + @Nonnull + String getId(); + + /** + * Gets the type of the repository, for example "default". + * + * @return The (case-sensitive) type of the repository, never {@code null}. + */ + @Nonnull + String getType(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java new file mode 100644 index 000000000000..e45a31e6954a --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java @@ -0,0 +1,24 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +public interface RepositoryMetadata extends Metadata +{ +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java new file mode 100644 index 000000000000..3de3372ac938 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -0,0 +1,337 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.ThreadSafe; + +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; +import java.util.List; +import java.util.NoSuchElementException; +import java.util.Optional; +import java.util.Properties; +import java.util.function.Predicate; + +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactDeployerException; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactFactoryException; +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactInstallerException; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactResolverException; +import org.apache.maven.api.services.ArtifactResolverResult; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyCollectorException; +import org.apache.maven.api.services.DependencyCollectorResult; +import org.apache.maven.api.services.DependencyFactory; +import org.apache.maven.api.services.DependencyResolver; +import org.apache.maven.api.services.DependencyResolverException; +import org.apache.maven.api.services.DependencyResolverResult; +import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.Service; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.settings.Settings; + +/** + * The session to install / deploy / resolve artifacts and dependencies. + */ +@ThreadSafe +public interface Session +{ + + @Nonnull + Settings getSettings(); + + @Nonnull + LocalRepository getLocalRepository(); + + @Nonnull + List getRemoteRepositories(); + + @Nonnull + SessionData getData(); + + @Nonnull + Properties getUserProperties(); + + @Nonnull + Properties getSystemProperties(); + + /** + * Retrieves the service for the interface + * + * @throws NoSuchElementException if the service could not be found + */ + @Nonnull + T getService( Class clazz ) throws NoSuchElementException; + + /** + * Creates a derived session using the given local repository. + * + * @param localRepository the new local repository + * @return the derived session + */ + @Nonnull + Session withLocalRepository( @Nonnull LocalRepository localRepository ); + + /** + * Creates a derived session using the given remote repositories. + * + * @param repositories the new list of remote repositories + * @return the derived session + */ + @Nonnull + Session withRemoteRepositories( @Nonnull List repositories ); + + /** + * Register the given listener which will receive all events. + * + * @param listener the listener to register + */ + void registerListener( @Nonnull Listener listener ); + + /** + * Unregisters a previously registered listener. + * + * @param listener the listener to unregister + */ + void unregisterListener( @Nonnull Listener listener ); + + /** + * Returns the list of registered listeners. + * + * @return an immutable collection of listeners + */ + @Nonnull + Collection getListeners(); + + /** + * Shortcut for getService(RepositoryFactory.class).createLocal(...) + * @see RepositoryFactory#createLocal(Path) + */ + default LocalRepository createLocalRepository( Path path ) + throws ArtifactFactoryException, IllegalArgumentException + { + return getService( RepositoryFactory.class ).createLocal( path ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * @see RepositoryFactory#createRemote(String, String) + */ + @Nonnull + default RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ) + { + return getService( RepositoryFactory.class ) + .createRemote( id, url ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * @see RepositoryFactory#createRemote(Repository) + */ + @Nonnull + default RemoteRepository createRemoteRepository( @Nonnull Repository repository ) + { + return getService( RepositoryFactory.class ) + .createRemote( repository ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see ArtifactFactory#create(Session, String, String, String, String) + */ + default Artifact createArtifact( String groupId, String artifactId, String version, String extension ) + throws ArtifactFactoryException, IllegalArgumentException + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, extension ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + default Artifact createArtifact( String groupId, String artifactId, String version, String classifier, + String extension, String type ) + throws ArtifactFactoryException, IllegalArgumentException + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, classifier, extension, type ); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see ArtifactResolver#resolve(Session, Artifact) + */ + default ArtifactResolverResult resolveArtifact( Artifact artifact ) + throws ArtifactResolverException, IllegalArgumentException + { + return getService( ArtifactResolver.class ) + .resolve( this, artifact ); + } + + /** + * Shortcut for getService(ArtifactInstaller.class).install(...) + * @see ArtifactInstaller#install(Session, Collection) + */ + default void installArtifacts( Artifact... artifacts ) + throws ArtifactInstallerException, IllegalArgumentException + { + installArtifacts( Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for getService(ArtifactInstaller.class).install(...) + * @see ArtifactInstaller#install(Session, Collection) + */ + default void installArtifacts( Collection artifacts ) + throws ArtifactInstallerException, IllegalArgumentException + { + getService( ArtifactInstaller.class ) + .install( this, artifacts ); + } + + /** + * Shortcut for getService(ArtifactDeployer.class).deploy(...) + * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection) + */ + default void deployArtifact( RemoteRepository repository, Artifact... artifacts ) + throws ArtifactDeployerException, IllegalArgumentException + { + getService( ArtifactDeployer.class ) + .deploy( this, repository, Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for getService(ArtifactManager.class).setPath(...) + * @see ArtifactManager#setPath(Artifact, Path) + */ + default void setArtifactPath( @Nonnull Artifact artifact, Path path ) + { + getService( ArtifactManager.class ) + .setPath( artifact, path ); + } + + /** + * Shortcut for getService(ArtifactManager.class).getPath(...) + * @see ArtifactManager#getPath(Artifact) + */ + @Nonnull + default Optional getArtifactPath( @Nonnull Artifact artifact ) + { + return getService( ArtifactManager.class ) + .getPath( artifact ); + } + + /** + * Shortcut for getService(ArtifactManager.class).isSnapshot(...) + * @see ArtifactManager#isSnapshot(String) + */ + default boolean isVersionSnapshot( @Nonnull String version ) + { + return getService( ArtifactManager.class ) + .isSnapshot( version ); + } + + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * @see DependencyFactory#create(Session, Artifact) + */ + default Dependency createDependency( Artifact artifact ) + { + return getService( DependencyFactory.class ) + .create( this, artifact ); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * @see DependencyCollector#collect(Session, Artifact) + */ + default DependencyCollectorResult collectDependencies( Artifact artifact ) + throws DependencyCollectorException, IllegalArgumentException + { + return getService( DependencyCollector.class ) + .collect( this, artifact ); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * @see DependencyCollector#collect(Session, Project) + */ + default DependencyCollectorResult collectDependencies( Project project ) + throws DependencyCollectorException, IllegalArgumentException + { + return getService( DependencyCollector.class ) + .collect( this, project ); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * @see DependencyCollector#collect(Session, Dependency) + */ + default DependencyCollectorResult collectDependencies( Dependency dependency ) + throws DependencyCollectorException, IllegalArgumentException + { + return getService( DependencyCollector.class ) + .collect( this, dependency ); + } + + /** + * Shortcut for getService(DependencyResolver.class).resolve(...) + * @see DependencyResolver#resolve(Session, Dependency, Predicate) + */ + default DependencyResolverResult resolveDependencies( Dependency dependency ) + throws DependencyResolverException, IllegalArgumentException + { + return getService( DependencyResolver.class ) + .resolve( this, dependency, null ); + } + + default Path getPathForLocalArtifact( Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalArtifact( this, getLocalRepository(), artifact ); + } + + default Path getPathForLocalMetadata( Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalMetadata( this, getLocalRepository(), metadata ); + } + + default Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteArtifact( this, getLocalRepository(), remote, artifact ); + } + + default Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteMetadata( this, getLocalRepository(), remote, metadata ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java new file mode 100644 index 000000000000..7b1b9c32ec2a --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java @@ -0,0 +1,84 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.ThreadSafe; + +import java.util.function.Supplier; + +/** + * A container for data that is specific to a session. + * All components may use this storage to associate arbitrary data with a session. + *

+ * Unlike a cache, this session data is not subject to purging. For this same reason, session data should also not be + * abused as a cache (i.e. for storing values that can be re-calculated) to avoid memory exhaustion. + *

+ * Note: Actual implementations must be thread-safe. + * + * @see Session#getData() + * @noimplement This interface is not intended to be implemented by clients. + * @noextend This interface is not intended to be extended by clients. + */ +@ThreadSafe +public interface SessionData +{ + + /** + * Associates the specified session data with the given key. + * + * @param key The key under which to store the session data, must not be {@code null}. + * @param value The data to associate with the key, may be {@code null} to remove the mapping. + */ + void set( @Nonnull Object key, @Nullable Object value ); + + /** + * Associates the specified session data with the given key if the key is currently mapped to the given value. This + * method provides an atomic compare-and-update of some key's value. + * + * @param key The key under which to store the session data, must not be {@code null}. + * @param oldValue The expected data currently associated with the key, may be {@code null}. + * @param newValue The data to associate with the key, may be {@code null} to remove the mapping. + * @return {@code true} if the key mapping was successfully updated from the old value to the new value, + * {@code false} if the current key mapping didn't match the expected value and was not updated. + */ + boolean set( @Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue ); + + /** + * Gets the session data associated with the specified key. + * + * @param key The key for which to retrieve the session data, must not be {@code null}. + * @return The session data associated with the key or {@code null} if none. + */ + @Nullable + Object get( @Nonnull Object key ); + + /** + * Retrieve of compute the data associated with the specified key. + * + * @param key The key for which to retrieve the session data, must not be {@code null}. + * @param supplier The supplier will compute the new value. + * @return The session data associated with the key. + */ + @Nullable + Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier supplier ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java new file mode 100644 index 000000000000..51dcb3b62459 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java @@ -0,0 +1,51 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import java.util.Map; + +/** + * Toolchain interface. + */ +public interface Toolchain +{ + /** + * get the type of toolchain. + * + * @return the toolchain type + */ + String getType(); + + /** + * Gets the platform tool executable. + * + * @param toolName the tool platform independent tool name. + * @return file representing the tool executable, or null if the tool can not be found + */ + String findTool( String toolName ); + + /** + * Let the toolchain decide if it matches requirements defined + * in the toolchain plugin configuration. + * @param requirements Map<String, String> key value pair, may not be {@code null} + * @return {@code true} if the requirements match, otherwise {@code false} + */ + boolean matchesRequirements( Map requirements ); +} \ No newline at end of file diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java new file mode 100644 index 000000000000..04dae3752e11 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java @@ -0,0 +1,45 @@ +package org.apache.maven.api.plugin; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Consumer; + +/** + * This interface forms the contract required for Mojos to interact with the Maven + * infrastructure.
+ * It features an execute() method, which triggers the Mojo's build-process behavior, and can throw + * a MojoExecutionException or MojoFailureException if error conditions occur.
+ * Also included is the setLog(...) method, which simply allows Maven to inject a logging mechanism which + * will allow the Mojo to communicate to the outside world through standard Maven channels. + */ +@FunctionalInterface @Consumer +public interface Mojo +{ + /** + * Perform whatever build-process behavior this Mojo implements.
+ * This is the main trigger for the Mojo inside the Maven system, and allows + * the Mojo to communicate errors. + * + * @throws MojoException if a problem occurs. + */ + void execute() + throws MojoException; + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java new file mode 100644 index 000000000000..2d50ca42a780 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java @@ -0,0 +1,94 @@ +package org.apache.maven.api.plugin; + +/* + * 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. + */ + +import org.apache.maven.api.services.MavenException; + +/** + * An exception occurring during the execution of a plugin.
+ */ +public class MojoException + extends MavenException +{ + + protected Object source; + + protected String longMessage; + + /** + * Construct a new MojoExecutionException exception providing the source and a short and long message: + * these messages are used to improve the message written at the end of Maven build. + */ + public MojoException( Object source, String shortMessage, String longMessage ) + { + super( shortMessage ); + this.source = source; + this.longMessage = longMessage; + } + + /** + * Construct a new MojoExecutionException exception wrapping an underlying Exception + * and providing a message. + */ + public MojoException( String message, Exception cause ) + { + super( message, cause ); + } + + /** + * Construct a new MojoExecutionException exception wrapping an underlying Throwable + * and providing a message. + */ + public MojoException( String message, Throwable cause ) + { + super( message, cause ); + } + + /** + * Construct a new MojoExecutionException exception providing a message. + */ + public MojoException( String message ) + { + super( message ); + } + + /** + * Constructs a new {@code MojoExecutionException} exception wrapping an underlying {@code Throwable}. + * + * @param cause the cause which is saved for later retrieval by the {@link #getCause()} method. + * A {@code null} value is permitted, and indicates that the cause is nonexistent or unknown. + * @since 3.8.3 + */ + public MojoException( Throwable cause ) + { + super( cause ); + } + + public String getLongMessage() + { + return longMessage; + } + + public Object getSource() + { + return source; + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java new file mode 100644 index 000000000000..d5f89ed580cd --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java @@ -0,0 +1,54 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to configure injection of Plexus components by + * + * MavenPluginManager.getConfiguredMojo(...). + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD } ) +@Inherited +public @interface Component +{ + /** + * role of the component to inject. + * @return the role + */ + Class role() default Object.class; + + /** + * hint of the component to inject. + * @return the hint + */ + String hint() default ""; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java new file mode 100644 index 000000000000..81ce2dfe71d7 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java @@ -0,0 +1,62 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used if your Mojo needs to fork a lifecycle. + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Execute +{ + /** + * lifecycle phase to fork. Note that specifying a phase overrides specifying a goal. + * @return the phase + */ + LifecyclePhase phase() default LifecyclePhase.NONE; + + /** + * goal to fork. Note that specifying a phase overrides specifying a goal. The specified goal must be + * another goal of the same plugin. + * @return the goal + */ + String goal() default ""; + + /** + * lifecycle id of the lifecycle that defines {@link #phase()}. Only valid in combination with {@link #phase()}. If + * not specified, Maven will use the lifecycle of the current build. + * + * @see Lifecycle Mappings + * @return the lifecycle id + */ + String lifecycle() default ""; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java new file mode 100644 index 000000000000..7cac629141dc --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java @@ -0,0 +1,46 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +/** + * Component instantiation strategy. + * + * @author Hervé Boutemy + * @since 3.0 + */ +public enum InstantiationStrategy +{ + PER_LOOKUP( "per-lookup" ), + SINGLETON( "singleton" ), + KEEP_ALIVE( "keep-alive" ), + POOLABLE( "poolable" ); + + private final String id; + + InstantiationStrategy( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java new file mode 100644 index 000000000000..a2bee4d56715 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java @@ -0,0 +1,77 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +/** + * Lifecycle phases. + * @author Olivier Lamy + * @since 3.0 + */ +public enum LifecyclePhase +{ + + VALIDATE( "validate" ), + INITIALIZE( "initialize" ), + GENERATE_SOURCES( "generate-sources" ), + PROCESS_SOURCES( "process-sources" ), + GENERATE_RESOURCES( "generate-resources" ), + PROCESS_RESOURCES( "process-resources" ), + COMPILE( "compile" ), + PROCESS_CLASSES( "process-classes" ), + GENERATE_TEST_SOURCES( "generate-test-sources" ), + PROCESS_TEST_SOURCES( "process-test-sources" ), + GENERATE_TEST_RESOURCES( "generate-test-resources" ), + PROCESS_TEST_RESOURCES( "process-test-resources" ), + TEST_COMPILE( "test-compile" ), + PROCESS_TEST_CLASSES( "process-test-classes" ), + TEST( "test" ), + PREPARE_PACKAGE( "prepare-package" ), + PACKAGE( "package" ), + PRE_INTEGRATION_TEST( "pre-integration-test" ), + INTEGRATION_TEST( "integration-test" ), + POST_INTEGRATION_TEST( "post-integration-test" ), + VERIFY( "verify" ), + INSTALL( "install" ), + DEPLOY( "deploy" ), + + PRE_CLEAN( "pre-clean" ), + CLEAN( "clean" ), + POST_CLEAN( "post-clean" ), + + PRE_SITE( "pre-site" ), + SITE( "site" ), + POST_SITE( "post-site" ), + SITE_DEPLOY( "site-deploy" ), + + NONE( "" ); + + private final String id; + + LifecyclePhase( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java new file mode 100644 index 000000000000..87eb8665e4f3 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java @@ -0,0 +1,89 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * This annotation will mark your class as a Mojo (ie. goal in a Maven plugin). + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) +@Inherited +public @interface Mojo +{ + /** + * goal name (required). + * @return the goal name + */ + String name(); + + /** + * default phase to bind your mojo. + * @return the default phase + */ + LifecyclePhase defaultPhase() default LifecyclePhase.NONE; + + /** + * the required dependency resolution scope. + * @return the required dependency resolution scope + */ + ResolutionScope requiresDependencyResolution() default ResolutionScope.NONE; + + /** + * the required dependency collection scope. + * @return the required dependency collection scope + */ + ResolutionScope requiresDependencyCollection() default ResolutionScope.NONE; + + /** + * does your mojo requires a project to be executed? + * @return requires a project + */ + boolean requiresProject() default true; + + /** + * if the Mojo uses the Maven project and its child modules. + * @return uses the Maven project and its child modules + */ + boolean aggregator() default false; + + /** + * does this Mojo need to be online to be executed? + * @return need to be online + */ + boolean requiresOnline() default false; + + /** + * own configurator class. + * @return own configurator class + */ + String configurator() default ""; + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java new file mode 100644 index 000000000000..6923a954296f --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java @@ -0,0 +1,92 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Inherited; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * Used to configure your Mojo parameters to be injected by + * + * MavenPluginManager.getConfiguredMojo(...). + *

+ * Beans injected into Mojo parameters are prepared by Sisu JSR330-based + * container: this annotation is only effective on fields of the Mojo class itself, nested bean injection + * requires Sisu or JSR330 annotations. + * + * @author Olivier Lamy + * @since 3.0 + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD } ) +@Inherited +public @interface Parameter +{ + /** + * name of the bean property used to get/set the field: by default, field name is used. + * @return the name of the bean property + */ + String name() default ""; + + /** + * alias supported to get parameter value. + * @return the alias + */ + String alias() default ""; + + /** + * Property to use to retrieve a value. Can come from -D execution, setting properties or pom + * properties. + * @return property name + */ + String property() default ""; + + /** + * parameter default value, may contain ${...} expressions which will be interpreted at + * inject time: see + * + * PluginParameterExpressionEvaluator. + * @return the default value + */ + String defaultValue() default ""; + + /** + * is the parameter required? + * @return true if the Mojo should fail when the parameter cannot be injected + */ + boolean required() default false; + + /** + * Specifies that this parameter cannot be configured directly by the user (as in the case of POM-specified + * configuration). This is useful when you want to force the user to use common POM elements rather than plugin + * configurations, as in the case where you want to use the artifact's final name as a parameter. In this case, you + * want the user to modify <build><finalName/></build> rather than specifying a value + * for finalName directly in the plugin configuration section. It is also useful to ensure that - for example - a + * List-typed parameter which expects items of type Artifact doesn't get a List full of Strings. + * + * @return true if the user should not be allowed to configure the parameter directly + */ + boolean readonly() default false; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java new file mode 100644 index 000000000000..5fe8862a7227 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java @@ -0,0 +1,76 @@ +package org.apache.maven.api.plugin.annotations; + +/* + * 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. + */ + +/** + * Dependencies resolution scopes available before + * mojo execution. + * + * Important note: The {@code id} values of this enum correspond to constants of + * {@code org.apache.maven.artifact.Artifact} class and MUST BE KEPT IN SYNC. + * + * @author Hervé Boutemy + * @since 3.0 + */ +public enum ResolutionScope +{ + /** + * empty resolution scope + */ + NONE( null ), + /** + * compile resolution scope + * = compile + system + provided dependencies + */ + COMPILE( "compile" ), + /** + * compile+runtime resolution scope (Maven 3 only) + * = compile + system + provided + runtime dependencies + */ + COMPILE_PLUS_RUNTIME( "compile+runtime" ), + /** + * runtime resolution scope + * = compile + runtime dependencies + */ + RUNTIME( "runtime" ), + /** + * runtime+system resolution scope (Maven 3 only) + * = compile + system + runtime dependencies + */ + RUNTIME_PLUS_SYSTEM( "runtime+system" ), + /** + * test resolution scope + * = compile + system + provided + runtime + test + * dependencies + */ + TEST( "test" ); + + private final String id; + + ResolutionScope( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java new file mode 100644 index 000000000000..c78f1ad491e2 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java @@ -0,0 +1,61 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.Collection; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.RemoteRepository; + +/** + * + */ +public interface ArtifactDeployer extends Service +{ + + /** + * @param request {@link ArtifactDeployerRequest} + * @throws ArtifactDeployerException in case of an error. + * @throws IllegalArgumentException in case of parameter request is null or parameter + * mavenArtifacts is null or mavenArtifacts.isEmpty() is + * true. + */ + void deploy( ArtifactDeployerRequest request ) + throws ArtifactDeployerException, IllegalArgumentException; + + /** + * @param session the repository session + * @param repository the repository to deploy to + * @param artifacts the collection of artifacts to deploy + * @throws ArtifactDeployerException in case of an error. + * @throws IllegalArgumentException in case of parameter request is null or parameter + * artifacts is null or artifacts.isEmpty() is + * true. + */ + default void deploy( Session session, + RemoteRepository repository, + Collection artifacts ) + throws ArtifactDeployerException, IllegalArgumentException + { + deploy( ArtifactDeployerRequest.build( session, repository, artifacts ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java new file mode 100644 index 000000000000..ca9d9c4a6709 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java @@ -0,0 +1,44 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +/** + * An artifact could not correctly being deployed. + * + */ +public class ArtifactDeployerException + extends MavenException +{ + + /** + * + */ + private static final long serialVersionUID = 7421964724059077698L; + + /** + * @param message The message of the error. + * @param e {@link Exception} + */ + public ArtifactDeployerException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java new file mode 100644 index 000000000000..84a78a538e7b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java @@ -0,0 +1,143 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.Collection; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.RemoteRepository; + +/** + * A request for deploying one or more artifacts to a remote repository. + */ +public interface ArtifactDeployerRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + RemoteRepository getRepository(); + + @Nonnull + Collection getArtifacts(); + + int getRetryFailedDeploymentCount(); + + @Nonnull + static ArtifactDeployerRequestBuilder builder() + { + return new ArtifactDeployerRequestBuilder(); + } + + @Nonnull + static ArtifactDeployerRequest build( Session session, RemoteRepository repository, Collection artifacts ) + { + return builder() + .session( session ) + .repository( repository ) + .artifacts( artifacts ) + .build(); + } + + class ArtifactDeployerRequestBuilder + { + Session session; + RemoteRepository repository; + Collection artifacts; + int retryFailedDeploymentCount; + + @Nonnull + public ArtifactDeployerRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + @Nonnull + public ArtifactDeployerRequestBuilder repository( RemoteRepository repository ) + { + this.repository = repository; + return this; + } + + public ArtifactDeployerRequestBuilder artifacts( Collection artifacts ) + { + this.artifacts = artifacts; + return this; + } + + public ArtifactDeployerRequestBuilder retryFailedDeploymentCount( int retryFailedDeploymentCount ) + { + this.retryFailedDeploymentCount = retryFailedDeploymentCount; + return this; + } + + @Nonnull + public ArtifactDeployerRequest build() + { + return new DefaultArtifactDeployerRequest( session, repository, artifacts, retryFailedDeploymentCount ); + } + + private static class DefaultArtifactDeployerRequest extends BaseRequest + implements ArtifactDeployerRequest + { + + private final RemoteRepository repository; + private final Collection artifacts; + private final int retryFailedDeploymentCount; + + DefaultArtifactDeployerRequest( @Nonnull Session session, + @Nonnull RemoteRepository repository, + @Nonnull Collection artifacts, + int retryFailedDeploymentCount ) + { + super( session ); + this.repository = requireNonNull( repository, "repository" ); + this.artifacts = unmodifiable( artifacts, "artifacts" ); + this.retryFailedDeploymentCount = retryFailedDeploymentCount; + } + + @Nonnull + @Override + public RemoteRepository getRepository() + { + return repository; + } + + @Nonnull + @Override + public Collection getArtifacts() + { + return artifacts; + } + + @Override + public int getRetryFailedDeploymentCount() + { + return retryFailedDeploymentCount; + } + } + + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java new file mode 100644 index 000000000000..c581a97ce1d4 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java @@ -0,0 +1,44 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +public interface ArtifactFactory extends Service +{ + + Artifact create( ArtifactFactoryRequest request ) + throws ArtifactFactoryException, IllegalArgumentException; + + default Artifact create( Session session, String groupId, String artifactId, String version, String extension ) + throws ArtifactFactoryException, IllegalArgumentException + { + return create( ArtifactFactoryRequest.build( session, groupId, artifactId, version, extension ) ); + } + + default Artifact create( Session session, String groupId, String artifactId, String version, + String classifier, String extension, String type ) + throws ArtifactFactoryException, IllegalArgumentException + { + return create( ArtifactFactoryRequest.build( session, groupId, artifactId, + version, classifier, extension, type ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java new file mode 100644 index 000000000000..2a1cf373dc99 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java @@ -0,0 +1,36 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +public class ArtifactFactoryException + extends MavenException +{ + + public ArtifactFactoryException( String message ) + { + super( message ); + } + + public ArtifactFactoryException( String message, Throwable cause ) + { + super( message, cause ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java new file mode 100644 index 000000000000..82cc44aed927 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java @@ -0,0 +1,197 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.Session; + +public interface ArtifactFactoryRequest +{ + + @Nonnull + Session getSession(); + + String getGroupId(); + + String getArtifactId(); + + String getVersion(); + + String getClassifier(); + + String getExtension(); + + String getType(); + + static ArtifactFactoryRequest build( Session session, String groupId, String artifactId, + String version, String extension ) + { + return ArtifactFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .extension( extension ) + .build(); + } + + static ArtifactFactoryRequest build( Session session, String groupId, String artifactId, + String version, String classifier, String extension, String type ) + { + return ArtifactFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .classifier( classifier ) + .extension( extension ) + .type( type ) + .build(); + } + + static ArtifactFactoryRequestBuilder builder() + { + return new ArtifactFactoryRequestBuilder(); + } + + class ArtifactFactoryRequestBuilder + { + private Session session; + private String groupId; + private String artifactId; + private String version; + private String classifier; + private String extension; + private String type; + + public ArtifactFactoryRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public ArtifactFactoryRequestBuilder groupId( String groupId ) + { + this.groupId = groupId; + return this; + } + + public ArtifactFactoryRequestBuilder artifactId( String artifactId ) + { + this.artifactId = artifactId; + return this; + } + + public ArtifactFactoryRequestBuilder version( String version ) + { + this.version = version; + return this; + } + + public ArtifactFactoryRequestBuilder classifier( String classifier ) + { + this.classifier = classifier; + return this; + } + + public ArtifactFactoryRequestBuilder extension( String extension ) + { + this.extension = extension; + return this; + } + + public ArtifactFactoryRequestBuilder type( String type ) + { + this.type = type; + return this; + } + + public ArtifactFactoryRequest build() + { + return new DefaultArtifactFactoryRequest( session, groupId, artifactId, version, + classifier, extension, type ); + } + + private static class DefaultArtifactFactoryRequest extends BaseRequest implements ArtifactFactoryRequest + { + private final String groupId; + private final String artifactId; + private final String version; + private final String classifier; + private final String extension; + private final String type; + + DefaultArtifactFactoryRequest( @Nonnull Session session, + String groupId, + String artifactId, + String version, + String classifier, + String extension, + String type ) + { + super( session ); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.classifier = classifier; + this.extension = extension; + this.type = type; + } + + @Override + public String getGroupId() + { + return groupId; + } + + @Override + public String getArtifactId() + { + return artifactId; + } + + @Override + public String getVersion() + { + return version; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getType() + { + return type; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java new file mode 100644 index 000000000000..b440a2818815 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java @@ -0,0 +1,71 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +/** + * @author Robert Scholte + */ +public interface ArtifactInstaller extends Service +{ + /** + * @param request {@link ArtifactInstallerRequest} + * @throws ArtifactInstallerException in case of an error. + * @throws IllegalArgumentException in case request is null. + */ + void install( ArtifactInstallerRequest request ) + throws ArtifactInstallerException, IllegalArgumentException; + + /** + * @param session the repository session + * @param artifact the {@link Artifact} to install + * @throws ArtifactInstallerException In case of an error which can be the a given artifact can not be found or the + * installation has failed. + * @throws IllegalArgumentException in case of parameter session is null or + * artifact is null. + */ + default void install( Session session, Artifact artifact ) + throws ArtifactInstallerException, IllegalArgumentException + { + install( session, Collections.singletonList( artifact ) ); + } + + /** + * @param session the repository session + * @param artifacts Collection of {@link Artifact MavenArtifacts} + * @throws ArtifactInstallerException In case of an error which can be the a given artifact can not be found or the + * installation has failed. + * @throws IllegalArgumentException in case of parameter request is null or parameter + * localRepository is null or localRepository is not a directory + * or parameter mavenArtifacts is null or + * mavenArtifacts.isEmpty() is true. + */ + default void install( Session session, Collection artifacts ) + throws ArtifactInstallerException + { + install( ArtifactInstallerRequest.build( session, artifacts ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java new file mode 100644 index 000000000000..18da90ab7493 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java @@ -0,0 +1,43 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +/** + * + */ +public class ArtifactInstallerException + extends MavenException +{ + + /** + * + */ + private static final long serialVersionUID = 3652561971360586373L; + + /** + * @param message The message of the error. + * @param e {@link Exception} + */ + public ArtifactInstallerException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java new file mode 100644 index 000000000000..9a62a2261321 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java @@ -0,0 +1,103 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; + +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +/** + * A request for installing one or more artifacts in the local repository. + */ +public interface ArtifactInstallerRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + Collection getArtifacts(); + + static ArtifactInstallerRequestBuilder builder() + { + return new ArtifactInstallerRequestBuilder(); + } + + static ArtifactInstallerRequest build( Session session, Collection artifacts ) + { + return builder() + .session( session ) + .artifacts( artifacts ) + .build(); + } + + class ArtifactInstallerRequestBuilder + { + Session session; + Collection artifacts = Collections.emptyList(); + + @Nonnull + public ArtifactInstallerRequestBuilder session( @Nonnull Session session ) + { + this.session = session; + return this; + } + + @Nonnull + public ArtifactInstallerRequestBuilder artifacts( @Nullable Collection artifacts ) + { + this.artifacts = artifacts != null ? artifacts : Collections.emptyList(); + return this; + } + + @Nonnull + public ArtifactInstallerRequest build() + { + return new DefaultArtifactInstallerRequest( session, artifacts ); + } + + static class DefaultArtifactInstallerRequest extends BaseRequest + implements ArtifactInstallerRequest + { + + private final Collection artifacts; + + DefaultArtifactInstallerRequest( @Nonnull Session session, + @Nonnull Collection artifacts ) + { + super( session ); + this.artifacts = unmodifiable( artifacts, "artifacts" ); + } + + @Nonnull + @Override + public Collection getArtifacts() + { + return artifacts; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java new file mode 100644 index 000000000000..cf9e211eb686 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java @@ -0,0 +1,62 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Optional; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Metadata; + +public interface ArtifactManager extends Service +{ + + /** + * Returns the path of the file previously associated to this artifact + * or Optional.empty() if no path has been associated. + */ + @Nonnull + Optional getPath( @Nonnull Artifact artifact ); + + /** + * Associates the given file path to the artifact. + */ + void setPath( @Nonnull Artifact artifact, Path path ); + + /** + * TODO: investigate removing the Metadata api completely + */ + @Nonnull + Collection getAttachedMetadatas( @Nonnull Artifact artifact ); + + /** + * TODO: investigate removing the Metadata api completely + */ + void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metadata ); + + /** + * Checks whether a given artifact version is considered a SNAPSHOT or not. + */ + boolean isSnapshot( String version ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java new file mode 100644 index 000000000000..25b6d133c8f0 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -0,0 +1,56 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +/** + * Resolves the artifact, i.e download the file when required and attach it to the artifact + */ +public interface ArtifactResolver extends Service +{ + + /** + * @param request {@link ArtifactResolverRequest} + * @return {@link ArtifactResolverResult} + * @throws ArtifactResolverException in case of an error. + * @throws NullPointerException in case of parameter buildingRequest is null or + * parameter mavenArtifact is null. + */ + ArtifactResolverResult resolve( ArtifactResolverRequest request ) + throws ArtifactResolverException, IllegalArgumentException; + + /** + * @param session {@link Session} + * @param artifact {@link Artifact} + * @return {@link ArtifactResolverResult} + * @throws ArtifactResolverException in case of an error. + * @throws NullPointerException in case of parameter buildingRequest is null or + * parameter coordinate is null. + */ + default ArtifactResolverResult resolve( Session session, + Artifact artifact ) + throws ArtifactResolverException, IllegalArgumentException + { + return resolve( ArtifactResolverRequest.build( session, artifact ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java new file mode 100644 index 000000000000..d5e442b1d5a7 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java @@ -0,0 +1,40 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +/** + * + */ +public class ArtifactResolverException + extends MavenException +{ + + private static final long serialVersionUID = 7252294837746943917L; + + /** + * @param message The message for the exception. + * @param e The exception itself. + */ + public ArtifactResolverException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java new file mode 100644 index 000000000000..16bfee844221 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java @@ -0,0 +1,101 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.Objects; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +/** + * A request for resolving an artifact. + */ +public interface ArtifactResolverRequest +{ + @Nonnull + Session getSession(); + + @Nonnull + Artifact getArtifact(); + + @Nonnull + static ArtifactResolverRequestBuilder builder() + { + return new ArtifactResolverRequestBuilder(); + } + + @Nonnull + static ArtifactResolverRequest build( Session session, Artifact artifact ) + { + return builder() + .session( session ) + .artifact( artifact ) + .build(); + } + + class ArtifactResolverRequestBuilder + { + Session session; + Artifact artifact; + + @Nonnull + public ArtifactResolverRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + @Nonnull + public ArtifactResolverRequestBuilder artifact( Artifact artifact ) + { + this.artifact = artifact; + return this; + } + + @Nonnull + public ArtifactResolverRequest build() + { + return new DefaultArtifactResolverRequest( session, artifact ); + } + + private static class DefaultArtifactResolverRequest extends BaseRequest implements ArtifactResolverRequest + { + @Nonnull + private final Artifact artifact; + + DefaultArtifactResolverRequest( @Nonnull Session session, + @Nonnull Artifact artifact ) + { + super( session ); + this.artifact = Objects.requireNonNull( artifact ); + } + + @Nonnull + @Override + public Artifact getArtifact() + { + return artifact; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java new file mode 100644 index 000000000000..9011405f3e1d --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Artifact; + +/** + * The Artifact Result + * + * @author Robert Scholte + * @since 3.0 + */ +public interface ArtifactResolverResult +{ + /** + * @return {@link Artifact} + */ + Artifact getArtifact(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java new file mode 100644 index 000000000000..515257adeb10 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java @@ -0,0 +1,66 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.Session; + +/** + * Base class for requests. + */ +abstract class BaseRequest +{ + + private final Session session; + + protected BaseRequest( @Nonnull Session session ) + { + this.session = requireNonNull( session, "session" ); + } + + @Nonnull + public Session getSession() + { + return session; + } + + public static T requireNonNull( T obj, String message ) + { + if ( obj == null ) + { + throw new IllegalArgumentException( message + " must mot be null" ); + } + return obj; + } + + protected static Collection unmodifiable( Collection obj, String message ) + { + if ( requireNonNull( obj, message ).isEmpty() ) + { + throw new IllegalArgumentException( message + " must not be empty" ); + } + return Collections.unmodifiableCollection( new ArrayList<>( obj ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java new file mode 100644 index 000000000000..2d222b76a299 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java @@ -0,0 +1,115 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Project; + +/** + * The DependencyCollector service can be used to collect dependencies + * for a given artifact and builds a graph of them. + * The dependencies collection mechanism will not download any artifacts, + * and only the pom files will be downloaded. + * + * @author Robert Scholte + * @author Guillaume Nodet + */ +public interface DependencyCollector extends Service +{ + + /** + * Collects the transitive dependencies and builds a dependency graph. + * Note that this operation is only concerned about determining the coordinates of the + * transitive dependencies and does not actually resolve the artifact files. + * + * @param request The dependency collection request, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * + * @see DependencyCollector#collect(Session, Project) + * @see DependencyCollector#collect(Session, Dependency) + * @see DependencyCollector#collect(Session, Artifact) + */ + @Nonnull + DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ) + throws DependencyCollectorException, IllegalArgumentException; + + /** + * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is + * only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the + * artifact files. + * + * @param session The {@link Session}, must not be {@code null}. + * @param root The Maven Dependency, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * @see #collect(DependencyCollectorRequest) + */ + @Nonnull + default DependencyCollectorResult collect( @Nonnull Session session, + @Nonnull Dependency root ) + throws DependencyCollectorException + { + return collect( DependencyCollectorRequest.build( session, root ) ); + } + + /** + * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is + * only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the + * artifact files. + * + * @param session The {@link Session}, must not be {@code null}. + * @param project The {@link Project}, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * @see #collect(DependencyCollectorRequest) + */ + @Nonnull + default DependencyCollectorResult collect( @Nonnull Session session, + @Nonnull Project project ) + throws DependencyCollectorException + { + return collect( DependencyCollectorRequest.build( session, project ) ); + } + + /** + * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is + * only concerned about determining the coordinates of the transitive dependencies and does not actually resolve the + * artifact files. + * + * @param session The {@link Session}, must not be {@code null}. + * @param artifact The {@link Artifact}, must not be {@code null}. + * @return The collection result, never {@code null}. + * @throws DependencyCollectorException If the dependency tree could not be built. + * @see #collect(DependencyCollectorRequest) + */ + @Nonnull + default DependencyCollectorResult collect( @Nonnull Session session, + @Nonnull Artifact artifact ) + throws DependencyCollectorException + { + return collect( DependencyCollectorRequest.build( session, artifact ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java new file mode 100644 index 000000000000..e04b557dad7b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +/** + * Thrown in case of bad artifact descriptors, version ranges or other issues encountered during calculation of the + * dependency graph. + */ +public class DependencyCollectorException + extends MavenException +{ + /** + * + */ + private static final long serialVersionUID = -3134726259840210686L; + + /** + * @param message The message you would give for the exception. + * @param cause The cause which is related to the message. + */ + public DependencyCollectorException( String message, Throwable cause ) + { + super( message, cause ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java new file mode 100644 index 000000000000..b2ff8d169615 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java @@ -0,0 +1,288 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +/** + * A request to collect the transitive dependencies and to build a dependency graph from them. There are three ways to + * create a dependency graph. First, only the root dependency can be given. Second, a root dependency and direct + * dependencies can be specified in which case the specified direct dependencies are merged with the direct dependencies + * retrieved from the artifact descriptor of the root dependency. And last, only direct dependencies can be specified in + * which case the root node of the resulting graph has no associated dependency. + * + * @see DependencyCollector#collect(DependencyCollectorRequest) + */ +public interface DependencyCollectorRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + Optional getRootArtifact(); + + @Nonnull + Optional getRoot(); + + @Nonnull + Collection getDependencies(); + + @Nonnull + Collection getManagedDependencies(); + + static DependencyCollectorRequest build( Session session, Artifact root ) + { + BaseRequest.requireNonNull( session, "session" ); + return builder() + .session( session ) + .root( session.createDependency( root ) ) + .build(); + } + + static DependencyCollectorRequest build( Session session, Dependency root ) + { + return builder() + .session( session ) + .root( root ) + .build(); + } + + static DependencyCollectorRequest build( Session session, Project project ) + { + BaseRequest.requireNonNull( session, "session" ); + return builder() + .session( session ) + .root( session.createDependency( project.getArtifact() ) ) + .dependencies( project.getDependencies() ) + .managedDependencies( project.getManagedDependencies() ) + .build(); + } + + static DependencyCollectorRequestBuilder builder() + { + return new DependencyCollectorRequestBuilder(); + } + + class DependencyCollectorRequestBuilder + { + + Session session; + Artifact rootArtifact; + Dependency root; + List dependencies = Collections.emptyList(); + List managedDependencies = Collections.emptyList(); + + @Nonnull + public DependencyCollectorRequestBuilder session( @Nonnull Session session ) + { + this.session = session; + return this; + } + + /** + * Sets the root artifact for the dependency graph. + * This must not be confused with {@link #root(Dependency)}: The root dependency, like any + * other specified dependency, will be subject to dependency collection/resolution, i.e. should have an artifact + * descriptor and a corresponding artifact file. The root artifact on the other hand is only used + * as a label for the root node of the graph in case no root dependency was specified. As such, the configured + * root artifact is ignored if {@link #root(Dependency)} has been set. + * + * @param rootArtifact The root artifact for the dependency graph, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder rootArtifact( Artifact rootArtifact ) + { + this.rootArtifact = rootArtifact; + return this; + } + + /** + * @param root The root dependency + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder root( @Nonnull Dependency root ) + { + this.root = root; + return this; + } + + /** + * Sets the direct dependencies. If both a root dependency and direct dependencies are given in the request, the + * direct dependencies from the request will be merged with the direct dependencies from the root dependency's + * artifact descriptor, giving higher priority to the dependencies from the request. + * + * @param dependencies The direct dependencies, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder dependencies( List dependencies ) + { + this.dependencies = ( dependencies != null ) ? dependencies : Collections.emptyList(); + return this; + } + + /** + * Adds the specified direct dependency. + * + * @param dependency The dependency to add, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DependencyCollectorRequestBuilder dependency( Dependency dependency ) + { + if ( dependency != null ) + { + if ( this.dependencies.isEmpty() ) + { + this.dependencies = new ArrayList<>(); + } + this.dependencies.add( dependency ); + } + return this; + } + + + /** + * Sets the dependency management to apply to transitive dependencies. To clarify, this management does not + * apply to + * the direct dependencies of the root node. + * + * @param managedDependencies The dependency management, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DependencyCollectorRequestBuilder managedDependencies( List managedDependencies ) + { + this.managedDependencies = ( managedDependencies != null ) ? managedDependencies : Collections.emptyList(); + return this; + } + + /** + * Adds the specified managed dependency. + * + * @param managedDependency The managed dependency to add, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + public DependencyCollectorRequestBuilder managedDependency( Dependency managedDependency ) + { + if ( managedDependency != null ) + { + if ( this.managedDependencies.isEmpty() ) + { + this.managedDependencies = new ArrayList<>(); + } + this.managedDependencies.add( managedDependency ); + } + return this; + } + + public DependencyCollectorRequest build() + { + return new DefaultDependencyCollectorRequest( + session, + rootArtifact, + root, + dependencies, + managedDependencies ); + } + + static class DefaultDependencyCollectorRequest extends BaseRequest + implements DependencyCollectorRequest + { + private final Artifact rootArtifact; + private final Dependency root; + private final Collection dependencies; + private final Collection managedDependencies; + + + /** + * Creates a request with the specified properties. + * + * @param session {@link Session} + * @param rootArtifact The root dependency whose transitive dependencies should be collected, may be {@code + * null}. + */ + DefaultDependencyCollectorRequest( + Session session, + Artifact rootArtifact, + Dependency root, + Collection dependencies, + Collection managedDependencies ) + { + super( session ); + this.rootArtifact = rootArtifact; + this.root = root; + this.dependencies = dependencies != null && !dependencies.isEmpty() + ? unmodifiable( dependencies, "dependencies" ) : Collections.emptyList(); + this.managedDependencies = managedDependencies != null && !managedDependencies.isEmpty() + ? unmodifiable( managedDependencies, "managedDependencies" ) : Collections.emptyList(); + + } + + @Nonnull + @Override + public Optional getRootArtifact() + { + return Optional.ofNullable( rootArtifact ); + } + + @Nonnull + @Override + public Optional getRoot() + { + return Optional.ofNullable( root ); + } + + @Nonnull + @Override + public Collection getDependencies() + { + return dependencies; + } + + @Nonnull + @Override + public Collection getManagedDependencies() + { + return managedDependencies; + } + + @Override + public String toString() + { + return getRoot() + " -> " + getDependencies(); + } + + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java new file mode 100644 index 000000000000..6020bffc15eb --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.api.Node; + +/** + * The result of a dependency collection request. + * + * @see DependencyCollector#collect(DependencyCollectorRequest) + */ +public interface DependencyCollectorResult +{ + /** + * Gets the exceptions that occurred while building the dependency graph. + * + * @return The exceptions that occurred, never {@code null}. + */ + List getExceptions(); + + /** + * Gets the root node of the dependency graph. + * + * @return The root node of the dependency graph or {@code null} if none. + */ + Node getRoot(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java new file mode 100644 index 000000000000..50e5849616f0 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; + +public interface DependencyFactory extends Service +{ + + Dependency create( DependencyFactoryRequest request ) + throws DependencyFactoryException, IllegalArgumentException; + + default Dependency create( Session session, Artifact artifact ) + throws DependencyFactoryException, IllegalArgumentException + { + return create( DependencyFactoryRequest.build( session, artifact ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java new file mode 100644 index 000000000000..e0c5f2fa8624 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java @@ -0,0 +1,36 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +public class DependencyFactoryException + extends MavenException +{ + + public DependencyFactoryException( String message ) + { + super( message ); + } + + public DependencyFactoryException( String message, Throwable cause ) + { + super( message, cause ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java new file mode 100644 index 000000000000..eafac2eb8704 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java @@ -0,0 +1,167 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Exclusion; + +public interface DependencyFactoryRequest +{ + + @Nonnull + Session getSession(); + + Artifact getArtifact(); + + String getScope(); + + boolean isOptional(); + + @Nonnull + Collection getExclusions(); + + static DependencyFactoryRequest build( Session session, Artifact artifact ) + { + return builder() + .session( session ) + .artifact( artifact ) + .build(); + } + + static DependencyFactoryRequestBuilder builder() + { + return new DependencyFactoryRequestBuilder(); + } + + class DependencyFactoryRequestBuilder + { + private Session session; + private Artifact artifact; + private String scope; + private boolean optional; + private Collection exclusions = Collections.emptyList(); + + public DependencyFactoryRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public DependencyFactoryRequestBuilder artifact( Artifact artifact ) + { + this.artifact = artifact; + return this; + } + + public DependencyFactoryRequestBuilder scope( String scope ) + { + this.scope = scope; + return this; + } + + public DependencyFactoryRequestBuilder optional( boolean optional ) + { + this.optional = optional; + return this; + } + + public DependencyFactoryRequestBuilder exclusions( Collection exclusions ) + { + if ( exclusions != null ) + { + if ( this.exclusions.isEmpty() ) + { + this.exclusions = new ArrayList<>(); + } + this.exclusions.addAll( exclusions ); + } + return this; + } + + public DependencyFactoryRequestBuilder exclusion( Exclusion exclusion ) + { + if ( exclusion != null ) + { + if ( this.exclusions.isEmpty() ) + { + this.exclusions = new ArrayList<>(); + } + this.exclusions.add( exclusion ); + } + return this; + } + + public DependencyFactoryRequest build() + { + return new DefaultDependencyFactoryRequest( session, artifact, scope, optional, exclusions ); + } + + private static class DefaultDependencyFactoryRequest extends BaseRequest implements DependencyFactoryRequest + { + private final Artifact artifact; + private final String scope; + private final boolean optional; + private final Collection exclusions; + + private DefaultDependencyFactoryRequest( @Nonnull Session session, Artifact artifact, String scope, + boolean optional, Collection exclusions ) + { + super( session ); + this.artifact = artifact; + this.scope = scope; + this.optional = optional; + this.exclusions = exclusions; + } + + @Override + public Artifact getArtifact() + { + return artifact; + } + + @Override + public String getScope() + { + return scope; + } + + @Override + public boolean isOptional() + { + return optional; + } + + @Nonnull + @Override + public Collection getExclusions() + { + return exclusions; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java new file mode 100644 index 000000000000..c4549d5bbcea --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java @@ -0,0 +1,90 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; +import java.util.function.Predicate; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; + +/** + * The DependencyResolver service can be used to collect the dependencies + * and download the artifacts. + * + * @author Robert Scholte + * @author Guillaume Nodet + */ +public interface DependencyResolver extends Service +{ + /** + * Collect dependencies and resolve the artifacts. + * + * @param request {@link DependencyResolverRequest} + * @return the resolved dependencies. + * @throws DependencyResolverException in case of an error. + */ + DependencyResolverResult resolve( DependencyResolverRequest request ) + throws DependencyResolverException; + + /** + * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. If + * the coordinate needs to be resolved too, use + * {@link #resolveDependencies(Session, List, List, Predicate< Node >)} passing + * {@code Collections.singletonList(coordinate)} + * + * @param session The {@link Session}, must not be {@code null}. + * @param root {@link Dependency} + * @param filter {@link Predicate} used to eventually filter out some dependencies + * when downloading (can be {@code null}). + * @return the resolved dependencies. + * @throws DependencyResolverException in case of an error. + */ + default DependencyResolverResult resolve( Session session, + Dependency root, + Predicate filter ) + throws DependencyResolverException + { + return resolve( DependencyResolverRequest.build( session, root, filter ) ); + } + + /** + * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. If + * the coordinate needs to be resolved too, use + * {@link #resolveDependencies(Session, List, List, Predicate< Node >)} passing + * {@code Collections.singletonList(coordinate)} + * + * @param session The {@link Session}, must not be {@code null}. + * @param project {@link Project} + * @param filter {@link Predicate< Node >} (can be {@code null}). + * @return the resolved dependencies. + * @throws DependencyResolverException in case of an error. + */ + default DependencyResolverResult resolve( Session session, + Project project, + Predicate filter ) + throws DependencyResolverException + { + return resolve( DependencyResolverRequest.build( session, project, filter ) ); + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/RuntimeInfo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java similarity index 52% rename from maven-settings/src/main/java/org/apache/maven/settings/RuntimeInfo.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java index 9020037f84d1..74bc04e8b341 100644 --- a/maven-settings/src/main/java/org/apache/maven/settings/RuntimeInfo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java @@ -1,4 +1,4 @@ -package org.apache.maven.settings; +package org.apache.maven.api.services; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,37 +19,36 @@ * under the License. */ -import java.io.File; - /** - * To handle runtime informations like local repository or profiles. - * + * The Exception class in case a resolving does not work. */ -@Deprecated -public class RuntimeInfo +public class DependencyResolverException + extends MavenException { - @SuppressWarnings( "checkstyle:constantname" ) - public static final String userHome = System.getProperty( "user.home" ); - - @SuppressWarnings( "checkstyle:constantname" ) - public static final File userMavenConfigurationHome = new File( userHome, ".m2" ); - - public static final File DEFAULT_USER_SETTINGS_FILE = new File( userMavenConfigurationHome, "settings.xml" ); - - private File settings; + private static final long serialVersionUID = 5320065249974323888L; - public RuntimeInfo() + /** + * @param cause The {@link Exception cause} of the problem. + */ + protected DependencyResolverException( Exception cause ) { - this.settings = DEFAULT_USER_SETTINGS_FILE; + super( cause ); } - public RuntimeInfo( File settings ) + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public DependencyResolverException( String message, Exception e ) { - this.settings = settings; + super( message, e ); } - public File getFile() + /** + * @return {@link DependencyResolverResult} + */ + public DependencyResolverResult getResult() { - return settings; + return null; } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java new file mode 100644 index 000000000000..e20e857b733b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java @@ -0,0 +1,327 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; + +/** + * A request to collect and resolve a dependency graph. + */ +public interface DependencyResolverRequest extends DependencyCollectorRequest +{ + + @Nonnull + Optional> getFilter(); + + @Nonnull + static DependencyResolverRequest build( @Nonnull Session session, + @Nonnull Artifact root ) + { + return build( session, root , null ); + } + + @Nonnull + static DependencyResolverRequest build( @Nonnull Session session, + @Nonnull Artifact root, + @Nullable Predicate filter ) + { + return builder() + .session( session ) + .rootArtifact( root ) + .filter( filter ) + .build(); + } + + @Nonnull + static DependencyResolverRequest build( @Nonnull Session session, + @Nonnull Dependency root ) + { + return build( session, root, null ); + } + + @Nonnull + static DependencyResolverRequest build( @Nonnull Session session, + @Nonnull Dependency root, + @Nullable Predicate filter ) + { + return builder() + .session( session ) + .root( root ) + .filter( filter ) + .build(); + } + + @Nonnull + static DependencyResolverRequest build( @Nonnull Session session, + @Nonnull Project project ) + { + return build( session, project, null ); + } + + @Nonnull + static DependencyResolverRequest build( @Nonnull Session session, + @Nonnull Project project, + @Nullable Predicate filter ) + { + BaseRequest.requireNonNull( session, "session" ); + return builder() + .session( session ) + .root( session.createDependency( project.getArtifact() ) ) + .dependencies( project.getDependencies() ) + .managedDependencies( project.getManagedDependencies() ) + .filter( filter ) + .build(); + } + + @Nonnull + static DependencyResolverRequestBuilder builder() + { + return new DependencyResolverRequestBuilder(); + } + + class DependencyResolverRequestBuilder + { + Session session; + Artifact rootArtifact; + Dependency root; + List dependencies = Collections.emptyList(); + List managedDependencies = Collections.emptyList(); + Predicate filter; + + @Nonnull + public DependencyResolverRequestBuilder session( @Nonnull Session session ) + { + this.session = session; + return this; + } + + /** + * Sets the root artifact for the dependency graph. + * This must not be confused with {@link #root(Dependency)}: The root dependency, like + * any other specified dependency, will be subject to dependency collection/resolution, i.e. should have an + * artifact descriptor and a corresponding artifact file. The root artifact on the other hand is only + * used as a label for the root node of the graph in case no root dependency was specified. As such, the + * configured root artifact is ignored if {@link #root(Dependency)} has not been called. + * + * @param rootArtifact The root artifact for the dependency graph, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyResolverRequestBuilder rootArtifact( Artifact rootArtifact ) + { + this.rootArtifact = rootArtifact; + return this; + } + + /** + * + * @param root The root dependency + * @return + */ + @Nonnull + public DependencyResolverRequestBuilder root( @Nonnull Dependency root ) + { + this.root = root; + return this; + } + + /** + * Sets the direct dependencies. If both a root dependency and direct dependencies are given in the request, the + * direct dependencies from the request will be merged with the direct dependencies from the root dependency's + * artifact descriptor, giving higher priority to the dependencies from the request. + * + * @param dependencies The direct dependencies, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyResolverRequestBuilder dependencies( List dependencies ) + { + this.dependencies = ( dependencies != null ) ? dependencies : Collections.emptyList(); + return this; + } + + /** + * Adds the specified direct dependency. + * + * @param dependency The dependency to add, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyResolverRequestBuilder dependency( Dependency dependency ) + { + if ( dependency != null ) + { + if ( this.dependencies.isEmpty() ) + { + this.dependencies = new ArrayList<>(); + } + this.dependencies.add( dependency ); + } + return this; + } + + + /** + * Sets the dependency management to apply to transitive dependencies. To clarify, this management does not + * apply to + * the direct dependencies of the root node. + * + * @param managedDependencies The dependency management, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyResolverRequestBuilder managedDependencies( List managedDependencies ) + { + this.managedDependencies = ( managedDependencies != null ) ? managedDependencies : Collections.emptyList(); + return this; + } + + /** + * Adds the specified managed dependency. + * + * @param managedDependency The managed dependency to add, may be {@code null}. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyResolverRequestBuilder managedDependency( Dependency managedDependency ) + { + if ( managedDependency != null ) + { + if ( this.managedDependencies.isEmpty() ) + { + this.managedDependencies = new ArrayList<>(); + } + this.managedDependencies.add( managedDependency ); + } + return this; + } + + @Nonnull + public DependencyResolverRequestBuilder filter( Predicate filter ) + { + this.filter = filter; + return this; + } + + @Nonnull + public DependencyResolverRequest build() + { + return new DefaultDependencyResolverRequest( + session, + rootArtifact, + root, + dependencies, + managedDependencies, + filter ); + } + + private static class DefaultDependencyResolverRequest extends BaseRequest + implements DependencyResolverRequest + { + private final Artifact rootArtifact; + private final Dependency root; + private final Collection dependencies; + private final Collection managedDependencies; + private final Predicate filter; + + + /** + * Creates a request with the specified properties. + * + * @param session {@link Session} + * @param rootArtifact The root dependency whose transitive dependencies should be collected, may be {@code + * null}. + */ + DefaultDependencyResolverRequest( + @Nonnull Session session, + @Nullable Artifact rootArtifact, + @Nullable Dependency root, + @Nullable Collection dependencies, + @Nullable Collection managedDependencies, + @Nullable Predicate filter ) + { + super( session ); + this.rootArtifact = rootArtifact; + this.root = root; + this.dependencies = dependencies != null && !dependencies.isEmpty() + ? unmodifiable( dependencies, "dependencies" ) : Collections.emptyList(); + this.managedDependencies = managedDependencies != null && !managedDependencies.isEmpty() + ? unmodifiable( managedDependencies, "managedDependencies" ) : Collections.emptyList(); + this.filter = filter; + } + + @Nonnull + @Override + public Optional getRootArtifact() + { + return Optional.ofNullable( rootArtifact ); + } + + @Nonnull + @Override + public Optional getRoot() + { + return Optional.ofNullable( root ); + } + + @Nonnull + @Override + public Collection getDependencies() + { + return dependencies; + } + + @Nonnull + @Override + public Collection getManagedDependencies() + { + return managedDependencies; + } + + @Nonnull + @Override + public Optional> getFilter() + { + return Optional.ofNullable( filter ); + } + + @Override + public String toString() + { + return getRoot() + " -> " + getDependencies(); + } + + } + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java new file mode 100644 index 000000000000..ff24cf61dc1e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java @@ -0,0 +1,44 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.api.Node; + +/** + * + * @author Robert Scholte + * + */ +public interface DependencyResolverResult +{ + /** + * Gets the exceptions that occurred while building the dependency graph. + * + * @return The list of exceptions {@link Exception}. + */ + List getCollectorExceptions(); + + Node getRoot(); + + List getArtifactResults(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java new file mode 100644 index 000000000000..fc9d3b1fbbad --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java @@ -0,0 +1,41 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Session; + +public interface LocalRepositoryManager extends Service +{ + + Path getPathForLocalArtifact( Session session, LocalRepository local, Artifact artifact ); + + Path getPathForLocalMetadata( Session session, LocalRepository local, Metadata metadata ); + + Path getPathForRemoteArtifact( Session session, LocalRepository local, RemoteRepository remote, Artifact artifact ); + + Path getPathForRemoteMetadata( Session session, LocalRepository local, RemoteRepository remote, Metadata metadata ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java new file mode 100644 index 000000000000..7b8338744057 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +public class MavenException extends RuntimeException +{ + public MavenException() + { + } + + public MavenException( String message ) + { + super( message ); + } + + public MavenException( String message, Throwable cause ) + { + super( message, cause ); + } + + public MavenException( Throwable cause ) + { + super( cause ); + } + + public MavenException( String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace ) + { + super( message, cause, enableSuppression, writableStackTrace ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java new file mode 100644 index 000000000000..78d10b0c3a3b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -0,0 +1,57 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +public interface ProjectBuilder extends Service +{ + + @Nonnull + ProjectBuilderResult build( ProjectBuilderRequest request ) + throws ProjectBuilderException, IllegalArgumentException; + + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) + throws ProjectBuilderException, IllegalArgumentException + { + return build( ProjectBuilderRequest.build( session, source ) ); + } + + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Path path ) + throws ProjectBuilderException, IllegalArgumentException + { + return build( ProjectBuilderRequest.build( session, path ) ); + } + + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Artifact artifact ) + throws ProjectBuilderException, IllegalArgumentException + { + return build( ProjectBuilderRequest.build( session, artifact ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java new file mode 100644 index 000000000000..018938592e29 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.services; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * The Exception class in case a resolving does not work. + */ +public class ProjectBuilderException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public ProjectBuilderException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java new file mode 100644 index 000000000000..af9dc4763590 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java @@ -0,0 +1,101 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +/** + * Describes a problem that was encountered during settings building. A problem can either be an exception that was + * thrown or a simple string message. In addition, a problem carries a hint about its source, e.g. the settings file + * that exhibits the problem. + * + * @author Benjamin Bentmann + * @author Robert Scholte + */ +public interface ProjectBuilderProblem +{ + + /** + * The different severity levels for a problem, in decreasing order. + */ + enum Severity + { + + FATAL, // + ERROR, // + WARNING // + + } + + /** + * Gets the hint about the source of the problem. While the syntax of this hint is unspecified and depends on the + * creator of the problem, the general expectation is that the hint provides sufficient information to the user to + * track the problem back to its origin. A concrete example for such a source hint can be the file path or URL from + * which the settings were read. + * + * @return The hint about the source of the problem or an empty string if unknown, never {@code null}. + */ + String getSource(); + + /** + * Gets the one-based index of the line containing the problem. The line number should refer to some text file that + * is given by {@link #getSource()}. + * + * @return The one-based index of the line containing the problem or a non-positive value if unknown. + */ + int getLineNumber(); + + /** + * Gets the one-based index of the column containing the problem. The column number should refer to some text file + * that is given by {@link #getSource()}. + * + * @return The one-based index of the column containing the problem or non-positive value if unknown. + */ + int getColumnNumber(); + + /** + * Gets the location of the problem. The location is a user-friendly combination of the values from + * {@link #getSource()}, {@link #getLineNumber()} and {@link #getColumnNumber()}. The exact syntax of the returned + * value is undefined. + * + * @return The location of the problem, never {@code null}. + */ + String getLocation(); + + /** + * Gets the exception that caused this problem (if any). + * + * @return The exception that caused this problem or {@code null} if not applicable. + */ + Exception getException(); + + /** + * Gets the message that describes this problem. + * + * @return The message describing this problem, never {@code null}. + */ + String getMessage(); + + /** + * Gets the severity level of this problem. + * + * @return The severity level of this problem, never {@code null}. + */ + Severity getSeverity(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java new file mode 100644 index 000000000000..e5f72997be85 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -0,0 +1,218 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; + +import java.nio.file.Path; +import java.util.Optional; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; + +public interface ProjectBuilderRequest +{ + + @Nonnull + Session getSession(); + + @Nonnull + Optional getPath(); + + @Nonnull + Optional getSource(); + + @Nonnull + Optional getArtifact(); + + boolean isAllowStubModel(); + + boolean isRecursive(); + + boolean isProcessPlugins(); + + boolean isResolveDependencies(); + + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) + { + return builder() + .session( session ) + .source( source ) + .build(); + } + + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Path path ) + { + return builder() + .session( session ) + .path( path ) + .build(); + } + + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Artifact artifact ) + { + return builder() + .session( session ) + .artifact( artifact ) + .build(); + } + + @Nonnull + static ProjectBuilderRequestBuilder builder() + { + return new ProjectBuilderRequestBuilder(); + } + + class ProjectBuilderRequestBuilder + { + Session session; + Path path; + ProjectBuilderSource source; + Artifact artifact; + boolean allowStubModel; + boolean recursive; + boolean processPlugins = true; + boolean resolveDependencies = true; + + public ProjectBuilderRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public ProjectBuilderRequestBuilder path( Path path ) + { + this.path = path; + return this; + } + + public ProjectBuilderRequestBuilder source( ProjectBuilderSource source ) + { + this.source = source; + return this; + } + + public ProjectBuilderRequestBuilder artifact( Artifact artifact ) + { + this.artifact = artifact; + return this; + } + + public ProjectBuilderRequestBuilder processPlugins( boolean processPlugins ) + { + this.processPlugins = processPlugins; + return this; + } + + public ProjectBuilderRequestBuilder resolveDependencies( boolean resolveDependencies ) + { + this.resolveDependencies = resolveDependencies; + return this; + } + + public ProjectBuilderRequest build() + { + return new DefaultProjectBuilderRequest( session, path, source, artifact, + allowStubModel, recursive, processPlugins, resolveDependencies ); + } + + private static class DefaultProjectBuilderRequest extends BaseRequest + implements ProjectBuilderRequest + { + private final Path path; + private final ProjectBuilderSource source; + private final Artifact artifact; + private final boolean allowStubModel; + private final boolean recursive; + private final boolean processPlugins; + private final boolean resolveDependencies; + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + DefaultProjectBuilderRequest( @Nonnull Session session, + @Nullable Path path, + @Nullable ProjectBuilderSource source, + @Nullable Artifact artifact, + boolean allowStubModel, + boolean recursive, + boolean processPlugins, + boolean resolveDependencies ) + { + super( session ); + this.path = path; + this.source = source; + this.artifact = artifact; + this.allowStubModel = allowStubModel; + this.recursive = recursive; + this.processPlugins = processPlugins; + this.resolveDependencies = resolveDependencies; + } + + @Nonnull + @Override + public Optional getPath() + { + return Optional.ofNullable( path ); + } + + @Nonnull + @Override + public Optional getSource() + { + return Optional.ofNullable( source ); + } + + @Nonnull + @Override + public Optional getArtifact() + { + return Optional.ofNullable( artifact ); + } + + @Override + public boolean isAllowStubModel() + { + return allowStubModel; + } + + @Override + public boolean isRecursive() + { + return recursive; + } + + @Override + public boolean isProcessPlugins() + { + return processPlugins; + } + + @Override + public boolean isResolveDependencies() + { + return resolveDependencies; + } + } + + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java new file mode 100644 index 000000000000..ea88e0272767 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java @@ -0,0 +1,76 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Optional; + +import org.apache.maven.api.Project; + +public interface ProjectBuilderResult +{ + + /** + * Gets the identifier of the project that could not be built. The general format of the identifier is {@code + * ::} but some of these coordinates may still be unknown at the point the exception + * is thrown so this information is merely meant to assist the user. + * + * @return The identifier of the project or an empty string if not known, never {@code null}. + */ + @Nonnull + String getProjectId(); + + /** + * Gets the POM file from which the project was built. + * + * @return The optional POM file. + */ + @Nonnull + Optional getPomFile(); + + /** + * Gets the project that was built. + * + * @return The project that was built or {@code null} if an error occurred and this result accompanies a + * {@link ProjectBuilderException}. + */ + @Nonnull + Optional getProject(); + + /** + * Gets the problems that were encountered during the project building. + * + * @return The problems that were encountered during the project building, can be empty but never {@code null}. + */ + @Nonnull + Collection getProblems(); + + /** + * Gets the result of the dependency resolution for the project. + * + * @return The result of the dependency resolution for the project. + */ + @Nonnull + Optional getDependencyResolverResult(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java new file mode 100644 index 000000000000..fd8c50d5b989 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java @@ -0,0 +1,30 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; + +public interface ProjectBuilderSource +{ + InputStream getInputStream() throws IOException; + + String getLocation(); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java new file mode 100644 index 000000000000..f66732265a7b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -0,0 +1,93 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Session; + +/** + * Interface to manage the project during its lifecycle + */ +public interface ProjectManager extends Service +{ + /** + * Returns the path to the resolved file in the local repository + * if the artifact has been resolved. + * + * @return the path of the resolved artifact + */ + @Nonnull + Optional getPath( Project project ); + + @Nonnull + Collection getAttachedArtifacts( Project project ); + + default void attachArtifact( Session session, Project project, Path path ) + { + String name = path.getFileName().toString(); + int dot = name.lastIndexOf( '.' ); + String ext = dot >= 1 ? name.substring( dot + 1 ) : ""; + Artifact artifact = session.createArtifact( project.getGroupId(), project.getArtifactId(), + project.getVersion(), ext ); + attachArtifact( project, artifact, path ); + } + + default void attachArtifact( Session session, Project project, String type, Path path ) + { + Artifact artifact = session.createArtifact( project.getGroupId(), project.getArtifactId(), + project.getVersion(), null, null, type ); + attachArtifact( project, artifact, path ); + } + + void attachArtifact( Project project, Artifact artifact, Path path ); + + List getCompileSourceRoots( Project project ); + + void addCompileSourceRoot( Project project, String sourceRoot ); + + List getTestCompileSourceRoots( Project project ); + + void addTestCompileSourceRoot( Project project, String sourceRoot ); + + List getRepositories( Project project ); + + List getResolvedDependencies( Project project, ResolutionScope scope ); + + Node getCollectedDependencies( Project project, ResolutionScope scope ); + + enum ResolutionScope + { + Compile, + CompileRuntime, + Runtime, + RuntimeSystem, + Test + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java new file mode 100644 index 000000000000..b430ad20032b --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.model.Repository; + +public interface RepositoryFactory extends Service +{ + + LocalRepository createLocal( Path path ); + + RemoteRepository createRemote( String id, String url ); + + RemoteRepository createRemote( Repository repository ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Service.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Service.java new file mode 100644 index 000000000000..fcf8d87fcddc --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Service.java @@ -0,0 +1,27 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.ThreadSafe; + +@ThreadSafe +public interface Service +{ +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java new file mode 100644 index 000000000000..4d61cfc1e0ff --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java @@ -0,0 +1,28 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Consumer; + +@Consumer +public interface ToolchainFactory +{ + // TODO: implement ToolchainFactory +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java new file mode 100644 index 000000000000..2740477689b2 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java @@ -0,0 +1,41 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Toolchain; + +public interface ToolchainManager extends Service +{ + List getToolchains( Session session, String type, Map requirements ) + throws ToolchainManagerException; + + Toolchain getToolchainFromBuildContext( Session session, String type ) + throws ToolchainManagerException; + + List getToolchainsForType( Session session, String type ) + throws ToolchainManagerException; + + void storeToolchainToBuildContext( Session session, Toolchain toolchain ) + throws ToolchainManagerException; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java new file mode 100644 index 000000000000..727e66d5967c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.services; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * The Exception class in case a resolving does not work. + */ +public class ToolchainManagerException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public ToolchainManagerException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java new file mode 100644 index 000000000000..668d139ba62a --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java @@ -0,0 +1,27 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.model.Model; + +public interface ModelXmlFactory extends XmlFactory +{ + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java new file mode 100644 index 000000000000..0bfee886d68c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java @@ -0,0 +1,27 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.settings.Settings; + +public interface SettingsXmlFactory extends XmlFactory +{ + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java new file mode 100644 index 000000000000..8e14b16b0a59 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java @@ -0,0 +1,27 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.toolchain.PersistedToolchains; + +public interface ToolchainsXmlFactory extends XmlFactory +{ + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java new file mode 100644 index 000000000000..a466533e97d3 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java @@ -0,0 +1,72 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.Service; + +public interface XmlFactory extends Service +{ + + @Nonnull + default T read( @Nonnull InputStream input ) throws XmlReaderException + { + return read( input, true ); + } + + @Nonnull + default T read( @Nonnull InputStream input, boolean strict ) throws XmlReaderException + { + return read( XmlReaderRequest.builder().inputStream( input ).strict( strict ).build() ); + } + + @Nonnull + default T read( @Nonnull Reader reader ) throws XmlReaderException + { + return read( reader, true ); + } + + @Nonnull + default T read( @Nonnull Reader reader, boolean strict ) throws XmlReaderException + { + return read( XmlReaderRequest.builder().reader( reader ).strict( strict ).build() ); + } + + @Nonnull + T read( @Nonnull XmlReaderRequest request ) throws XmlReaderException; + + default void write( @Nonnull T content, @Nonnull OutputStream outputStream ) throws XmlWriterException + { + write( XmlWriterRequest.builder().content( content ).outputStream( outputStream ).build() ); + } + + default void write( @Nonnull T content, @Nonnull Writer writer ) throws XmlWriterException + { + write( XmlWriterRequest.builder().content( content ).writer( writer ).build() ); + } + + void write( @Nonnull XmlWriterRequest request ) throws XmlWriterException; + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java new file mode 100644 index 000000000000..b5cd94ce0202 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java @@ -0,0 +1,40 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.services.MavenException; + +/** + * + */ +public class XmlReaderException + extends MavenException +{ + + /** + * @param message The message for the exception. + * @param e The exception itself. + */ + public XmlReaderException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java new file mode 100644 index 000000000000..31a30681e263 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java @@ -0,0 +1,222 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.Reader; +import java.net.URL; +import java.nio.file.Path; + +public interface XmlReaderRequest +{ + + Path getPath(); + + URL getURL(); + + InputStream getInputStream(); + + Reader getReader(); + + Transformer getTransformer(); + + boolean isStrict(); + + String getModelId(); + + String getLocation(); + + boolean isAddDefaultEntities(); + + interface Transformer + { + /** + * Interpolate the value read from the xml document + * + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + + static XmlReaderRequestBuilder builder() + { + return new XmlReaderRequestBuilder(); + } + + class XmlReaderRequestBuilder + { + Path path; + URL url; + InputStream inputStream; + Reader reader; + Transformer transformer; + boolean strict; + String modelId; + String location; + boolean addDefaultEntities = true; + + public XmlReaderRequestBuilder path( Path path ) + { + this.path = path; + return this; + } + + public XmlReaderRequestBuilder url( URL url ) + { + this.url = url; + return this; + } + + public XmlReaderRequestBuilder inputStream( InputStream inputStream ) + { + this.inputStream = inputStream; + return this; + } + + public XmlReaderRequestBuilder reader( Reader reader ) + { + this.reader = reader; + return this; + } + + public XmlReaderRequestBuilder transformer( Transformer transformer ) + { + this.transformer = transformer; + return this; + } + + public XmlReaderRequestBuilder strict( boolean strict ) + { + this.strict = strict; + return this; + } + + public XmlReaderRequestBuilder modelId( String modelId ) + { + this.modelId = modelId; + return this; + } + + public XmlReaderRequestBuilder location( String location ) + { + this.location = location; + return this; + } + + public XmlReaderRequestBuilder addDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + return this; + } + + public XmlReaderRequest build() + { + return new DefaultXmlReaderRequest( path, url, inputStream, reader, transformer, strict, + modelId, location, addDefaultEntities ); + } + + private static class DefaultXmlReaderRequest implements XmlReaderRequest + { + final Path path; + final URL url; + final InputStream inputStream; + final Reader reader; + final Transformer transformer; + final boolean strict; + final String modelId; + final String location; + final boolean addDefaultEntities; + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + DefaultXmlReaderRequest( Path path, URL url, InputStream inputStream, Reader reader, + Transformer transformer, boolean strict, + String modelId, String location, + boolean addDefaultEntities ) + { + this.path = path; + this.url = url; + this.inputStream = inputStream; + this.reader = reader; + this.transformer = transformer; + this.strict = strict; + this.modelId = modelId; + this.location = location; + this.addDefaultEntities = addDefaultEntities; + } + + @Override + public Path getPath() + { + return path; + } + + @Override + public URL getURL() + { + return null; + } + + @Override + public InputStream getInputStream() + { + return inputStream; + } + + public Reader getReader() + { + return reader; + } + + @Override + public Transformer getTransformer() + { + return transformer; + } + + @Override + public boolean isStrict() + { + return strict; + } + + @Override + public String getModelId() + { + return modelId; + } + + @Override + public String getLocation() + { + return location; + } + + @Override + public boolean isAddDefaultEntities() + { + return addDefaultEntities; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java new file mode 100644 index 000000000000..6ac5f4cf63cb --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java @@ -0,0 +1,40 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import org.apache.maven.api.services.MavenException; + +/** + * + */ +public class XmlWriterException + extends MavenException +{ + + /** + * @param message The message for the exception. + * @param e The exception itself. + */ + public XmlWriterException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java new file mode 100644 index 000000000000..d504f44cb212 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java @@ -0,0 +1,100 @@ +package org.apache.maven.api.services.xml; + +/* + * 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. + */ + +import java.io.OutputStream; +import java.io.Writer; + +public interface XmlWriterRequest +{ + + OutputStream getOutputStream(); + + Writer getWriter(); + + T getContent(); + + static XmlWriterRequestBuilder builder() + { + return new XmlWriterRequestBuilder<>(); + } + + class XmlWriterRequestBuilder + { + OutputStream outputStream; + Writer writer; + T content; + + public XmlWriterRequestBuilder outputStream( OutputStream outputStream ) + { + this.outputStream = outputStream; + return this; + } + + public XmlWriterRequestBuilder writer( Writer writer ) + { + this.writer = writer; + return this; + } + + public XmlWriterRequestBuilder content( T content ) + { + this.content = content; + return this; + } + + public XmlWriterRequest build() + { + return new DefaultXmlWriterRequest<>( outputStream, writer, content ); + } + + private static class DefaultXmlWriterRequest implements XmlWriterRequest + { + final OutputStream outputStream; + final Writer writer; + final T content; + + DefaultXmlWriterRequest( OutputStream outputStream, Writer writer, T content ) + { + this.outputStream = outputStream; + this.writer = writer; + this.content = content; + } + + @Override + public OutputStream getOutputStream() + { + return outputStream; + } + + @Override + public Writer getWriter() + { + return writer; + } + + @Override + public T getContent() + { + return content; + } + } + } +} diff --git a/api/maven-api-meta/pom.xml b/api/maven-api-meta/pom.xml new file mode 100644 index 000000000000..85e90e3f5ffe --- /dev/null +++ b/api/maven-api-meta/pom.xml @@ -0,0 +1,32 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-meta + Apache Maven API Meta annotations + + diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java new file mode 100644 index 000000000000..3e95c7480653 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A type implemented by, or extended by maven plugins or extensions. + * Maven plugins or extensions may provide implementations of those types which will be used by maven. + * + * A type can be marked {@link Consumer} or {@link Provider} but not both. A type is assumed to be + * {@link Consumer} if it is not marked either {@link Consumer} or {@link Provider}. + * + * A package can be marked {@link Provider}. In this case, all types in the package are considered + * to be a provider type regardless of whether they are marked {@link Consumer} or {@link Provider}. + * + * @see Provider + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Consumer +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java new file mode 100644 index 000000000000..efae138c7de7 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java @@ -0,0 +1,30 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Generated +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java new file mode 100644 index 000000000000..865f8d09c3a0 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java @@ -0,0 +1,30 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Immutable +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java new file mode 100644 index 000000000000..7b536e11ae38 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java @@ -0,0 +1,37 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * The annotated element must not be null. + *

+ * Annotated fields must not be null after construction has completed. + *

+ * When this annotation is applied to a method it applies to the method return value. + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Nonnull +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java new file mode 100644 index 000000000000..e50dc3d58d36 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java @@ -0,0 +1,30 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Nullable +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java new file mode 100644 index 000000000000..0bdbcfca2395 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java @@ -0,0 +1,42 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * A type implemented by, or extended by maven itself. + * Maven provides implementations of those types and may inject them in plugins. + * + * A type can be marked {@link Consumer} or {@link Provider} but not both. A type is assumed to be + * {@link Consumer} if it is not marked either {@link Consumer} or {@link Provider}. + * + * A package can be marked {@link Provider}. In this case, all types in the package are considered + * to be a provider type regardless of whether they are marked {@link Consumer} or {@link Provider}. + * + * @see Consumer + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Provider +{ +} diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java new file mode 100644 index 000000000000..4cad58984343 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java @@ -0,0 +1,30 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface ThreadSafe +{ +} diff --git a/api/maven-api-model/pom.xml b/api/maven-api-model/pom.xml new file mode 100644 index 000000000000..cd2111693751 --- /dev/null +++ b/api/maven-api-model/pom.xml @@ -0,0 +1,101 @@ + + + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-model + + Maven Model + Model for Maven POM (Project Object Model) + + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + attach-mdo + + attach-artifact + + + + + src/main/mdo/maven.mdo + mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + 5.0.0 + + src/main/mdo/maven.mdo + + + + + + + + modello + + velocity + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + + + + + diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java new file mode 100644 index 000000000000..98d9ef8a29fe --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -0,0 +1,201 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +import java.io.Serializable; +import java.util.Collection; +import java.util.Collections; +import java.util.HashMap; +import java.util.LinkedHashMap; +import java.util.Map; + +/** + * Class InputLocation. + */ +public class InputLocation + implements Serializable, InputLocationTracker +{ + private final int lineNumber; + private final int columnNumber; + private final InputSource source; + private final Map locations; + + public InputLocation( InputSource source ) + { + this.lineNumber = -1; + this.columnNumber = -1; + this.source = source; + this.locations = Collections.singletonMap( 0, this ); + } + + public InputLocation( int lineNumber, int columnNumber ) + { + this( lineNumber, columnNumber, null, null ); + } + + public InputLocation( int lineNumber, int columnNumber, InputSource source ) + { + this( lineNumber, columnNumber, source, null ); + } + + public InputLocation( int lineNumber, int columnNumber, InputSource source, Object selfLocationKey ) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + this.source = source; + this.locations = selfLocationKey != null + ? Collections.singletonMap( selfLocationKey, this ) : Collections.emptyMap(); + } + + public InputLocation( int lineNumber, int columnNumber, InputSource source, Map locations ) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + this.source = source; + this.locations = locations != null + ? Collections.unmodifiableMap( new HashMap<>( locations ) ) : Collections.emptyMap(); + } + + public int getLineNumber() + { + return lineNumber; + } + + public int getColumnNumber() + { + return columnNumber; + } + + public InputSource getSource() + { + return source; + } + + public InputLocation getLocation( Object key ) + { + return locations != null ? locations.get( key ) : null; + } + + public Map getLocations() + { + return locations; + } + + /** + * Method merge. + */ + public static InputLocation merge( InputLocation target, InputLocation source, boolean sourceDominant ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + Map locations; + Map sourceLocations = source.locations; + Map targetLocations = target.locations; + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new LinkedHashMap<>(); + locations.putAll( sourceDominant ? targetLocations : sourceLocations ); + locations.putAll( sourceDominant ? sourceLocations : targetLocations ); + } + + return new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations ); + } //-- InputLocation merge( InputLocation, InputLocation, boolean ) + + /** + * Method merge. + */ + public static InputLocation merge( InputLocation target, InputLocation source, Collection indices ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + Map locations; + Map sourceLocations = source.locations; + Map targetLocations = target.locations; + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new LinkedHashMap<>(); + for ( int index : indices ) + { + InputLocation location; + if ( index < 0 ) + { + location = sourceLocations.get( ~index ); + } + else + { + location = targetLocations.get( index ); + } + locations.put( locations.size(), location ); + } + } + + return new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource(), locations ); + } //-- InputLocation merge( InputLocation, InputLocation, java.util.Collection ) + + /** + * Class StringFormatter. + * + * @version $Revision$ $Date$ + */ + public interface StringFormatter + { + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method toString. + */ + String toString( InputLocation location ); + + } + +} diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java new file mode 100644 index 000000000000..e90934813ab8 --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocationTracker.java @@ -0,0 +1,26 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +public interface InputLocationTracker +{ + InputLocation getLocation( Object field ); +} + diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java new file mode 100644 index 000000000000..34c8bf642a6f --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputSource.java @@ -0,0 +1,61 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +import java.io.Serializable; + +/** + * Class InputSource. + */ +public class InputSource + implements Serializable +{ + + private final String modelId; + private final String location; + + public InputSource( String modelId, String location ) + { + this.modelId = modelId; + this.location = location; + } + + /** + * Get the path/URL of the POM or {@code null} if unknown. + */ + public String getLocation() + { + return this.location; + } + + /** + * Get the identifier of the POM in the format {@code ::}. + */ + public String getModelId() + { + return this.modelId; + } + + @Override + public String toString() + { + return getModelId() + " " + getLocation(); + } +} diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java new file mode 100644 index 000000000000..9de3eb443f19 --- /dev/null +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java @@ -0,0 +1,120 @@ +package org.apache.maven.api.model; + +/* + * 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. + */ + +import java.util.Map; +import java.util.Properties; +import java.util.function.BiFunction; +import java.util.function.Function; + +class ROProperties extends Properties +{ + ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object remove( Object key ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void putAll( Map t ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void clear() + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object replace( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/package-info.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/package-info.java similarity index 96% rename from maven-model/src/main/java/org/apache/maven/model/package-info.java rename to api/maven-api-model/src/main/java/org/apache/maven/api/model/package-info.java index 88d3fa0701e6..bfcdbe273c51 100644 --- a/maven-model/src/main/java/org/apache/maven/model/package-info.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/package-info.java @@ -3,7 +3,7 @@ * Maven POM (Project Object Model) classes, generated from maven.mdo model. * The root class is {@link org.apache.maven.model.Model}. */ -package org.apache.maven.model; +package org.apache.maven.api.model; /* * Licensed to the Apache Software Foundation (ASF) under one diff --git a/maven-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo similarity index 93% rename from maven-model/src/main/mdo/maven.mdo rename to api/maven-api-model/src/main/mdo/maven.mdo index 3de0f2e0264d..20c72048c809 100644 --- a/maven-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -66,7 +66,7 @@ - + Model ModelBase @@ -78,6 +78,14 @@ 3.0.0+ + + pomFile + 5.0.0+ + false + Originating POM file + java.nio.file.Path + + @@ -353,19 +361,9 @@ - 4.0.0+ + 4.0.0/4.1.0 - 4.0.0+ + 5.0.0+ groupId:artifactId:packaging:version + */ + public String getId() + { + StringBuilder id = new StringBuilder( 64 ); + + id.append( ( getGroupId() == null ) ? "[inherited]" : getGroupId() ); + id.append( ":" ); + id.append( getArtifactId() ); + id.append( ":" ); + id.append( getPackaging() ); + id.append( ":" ); + id.append( ( getVersion() == null ) ? "[inherited]" : getVersion() ); + + return id.toString(); + } + + @Override + public String toString() { - return ( childProjectUrlInheritAppendPath != null ) ? Boolean.parseBoolean( childProjectUrlInheritAppendPath ) : true; + return getId(); } - public void setChildProjectUrlInheritAppendPath( boolean childProjectUrlInheritAppendPath ) + public boolean isChildProjectUrlInheritAppendPath() { - this.childProjectUrlInheritAppendPath = String.valueOf( childProjectUrlInheritAppendPath ); + return ( getChildProjectUrlInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildProjectUrlInheritAppendPath() ) : true; } ]]> @@ -439,7 +477,7 @@ - + ModelBase 3.0.0+ @@ -537,16 +575,6 @@ * - - reports - 4.0.0+ - - Deprecated. Now ignored by Maven. - ]]> - - DOM - reporting 4.0.0+ @@ -564,7 +592,7 @@ - + PluginContainer 3.0.0+ Contains the plugins informations for the project. @@ -584,7 +612,7 @@ 4.0.0+ pluginMap; + Map pluginMap; /** * Reset the pluginsMap field to null @@ -598,14 +626,14 @@ * @return a Map of plugins field with Plugins#getKey() as key * @see org.apache.maven.model.Plugin#getKey() */ - public synchronized java.util.Map getPluginsAsMap() + public synchronized Map getPluginsAsMap() { if ( pluginMap == null ) { pluginMap = new java.util.LinkedHashMap(); - if ( plugins != null ) + if ( getPlugins() != null ) { - for ( java.util.Iterator it = plugins.iterator(); it.hasNext(); ) + for ( java.util.Iterator it = getPlugins().iterator(); it.hasNext(); ) { Plugin plugin = (Plugin) it.next(); pluginMap.put( plugin.getKey(), plugin ); @@ -793,7 +821,7 @@ - + CiManagement 4.0.0+ @@ -832,7 +860,7 @@ - + Notifier Configures one method for notifying users/developers when a build breaks. 4.0.0+ @@ -894,7 +922,7 @@ - + Contributor Description of a person who has contributed to the project, but who does not have commit privileges. Usually, these contributions come in the form of patches submitted. @@ -972,7 +1000,7 @@ - + Dependency 3.0.0+ @@ -1118,12 +1146,7 @@ @@ -1140,7 +1163,7 @@ 4.0.0+ groupId:artifactId:type @@ -1149,18 +1172,10 @@ { if ( managementKey == null ) { - managementKey = groupId + ":" + artifactId + ":" + type + ( classifier != null ? ":" + classifier : "" ); + managementKey = getGroupId() + ":" + getArtifactId() + ":" + getType() + ( getClassifier() != null ? ":" + getClassifier() : "" ); } return managementKey; } - - /** - * Clears the management key in case one field has been modified. - */ - public void clearManagementKey() - { - managementKey = null; - } ]]> @@ -1180,7 +1195,7 @@ - + Exclusion 4.0.0+ @@ -1206,7 +1221,7 @@ - + IssueManagement Information about the issue tracking (or bug tracking) system used to manage this project. @@ -1226,7 +1241,7 @@ - + DistributionManagement 4.0.0+ This elements describes all that pertains to distribution for a project. It is @@ -1303,7 +1318,7 @@ - + License Describes the licenses for this project. This is used to generate the license page of the project's web site, as well as being taken into consideration in other reporting @@ -1347,7 +1362,7 @@ - + MailingList 3.0.0+ This element describes all of the mailing lists associated with a project. The @@ -1422,7 +1437,7 @@ and maybe even a specific element for the user and scm mailing lists. Then leave the more lose structure for any other type of mailing list. - + Organization Specifies the organization that produces this project. 3.0.0+ @@ -1441,7 +1456,7 @@ - + PatternSet 3.0.0+ Definition of include or exclude patterns. @@ -1509,7 +1524,7 @@ - + Parent 4.0.0+ @@ -1596,7 +1611,7 @@ - + Scm 4.0.0+ @@ -1706,32 +1721,17 @@ public boolean isChildScmConnectionInheritAppendPath() { - return ( childScmConnectionInheritAppendPath != null ) ? Boolean.parseBoolean( childScmConnectionInheritAppendPath ) : true; - } - - public void setChildScmConnectionInheritAppendPath( boolean childScmConnectionInheritAppendPath ) - { - this.childScmConnectionInheritAppendPath = String.valueOf( childScmConnectionInheritAppendPath ); + return ( getChildScmConnectionInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildScmConnectionInheritAppendPath() ) : true; } public boolean isChildScmDeveloperConnectionInheritAppendPath() { - return ( childScmDeveloperConnectionInheritAppendPath != null ) ? Boolean.parseBoolean( childScmDeveloperConnectionInheritAppendPath ) : true; - } - - public void setChildScmDeveloperConnectionInheritAppendPath( boolean childScmDeveloperConnectionInheritAppendPath ) - { - this.childScmDeveloperConnectionInheritAppendPath = String.valueOf( childScmDeveloperConnectionInheritAppendPath ); + return ( getChildScmDeveloperConnectionInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildScmDeveloperConnectionInheritAppendPath() ) : true; } public boolean isChildScmUrlInheritAppendPath() { - return ( childScmUrlInheritAppendPath != null ) ? Boolean.parseBoolean( childScmUrlInheritAppendPath ) : true; - } - - public void setChildScmUrlInheritAppendPath( boolean childScmUrlInheritAppendPath ) - { - this.childScmUrlInheritAppendPath = String.valueOf( childScmUrlInheritAppendPath ); + return ( getChildScmUrlInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildScmUrlInheritAppendPath() ) : true; } ]]> @@ -1827,24 +1827,9 @@ 4.0.0+ - + RepositoryBase 4.0.0+ A repository contains the information needed for establishing connections with @@ -1955,7 +1940,7 @@ - + RepositoryPolicy 4.0.0+ Download policy. @@ -2013,12 +1998,7 @@ public boolean isEnabled() { - return ( enabled != null ) ? Boolean.parseBoolean( enabled ) : true; - } - - public void setEnabled( boolean enabled ) - { - this.enabled = String.valueOf( enabled ); + return ( getEnabled() != null ) ? Boolean.parseBoolean( getEnabled() ) : true; } ]]> @@ -2028,7 +2008,7 @@ - + Site 4.0.0+ Contains the information needed for deploying websites. @@ -2085,12 +2065,7 @@ public boolean isChildSiteUrlInheritAppendPath() { - return ( childSiteUrlInheritAppendPath != null ) ? Boolean.parseBoolean( childSiteUrlInheritAppendPath ) : true; - } - - public void setChildSiteUrlInheritAppendPath( boolean childSiteUrlInheritAppendPath ) - { - this.childSiteUrlInheritAppendPath = String.valueOf( childSiteUrlInheritAppendPath ); + return ( getChildSiteUrlInheritAppendPath() != null ) ? Boolean.parseBoolean( getChildSiteUrlInheritAppendPath() ) : true; } ]]> @@ -2099,7 +2074,7 @@ - + ConfigurationContainer 4.0.0+ Contains the configuration information of the container like Plugin. @@ -2144,25 +2119,9 @@ @@ -2231,16 +2190,6 @@ * - - goals - 4.0.0+ - - Deprecated. Unused by Maven. - ]]> - - DOM - @@ -2249,16 +2198,10 @@ executionMap = null; - /** * Reset the executionMap field to null */ @@ -2266,7 +2209,6 @@ { this.executionMap = null; } - /** * @return a Map of executions field with PluginExecution#getId() as key * @see org.apache.maven.model.PluginExecution#getId() @@ -2276,22 +2218,16 @@ if ( executionMap == null ) { executionMap = new java.util.LinkedHashMap(); - if ( getExecutions() != null ) + for ( java.util.Iterator i = getExecutions().iterator(); i.hasNext(); ) { - for ( java.util.Iterator i = getExecutions().iterator(); i.hasNext(); ) + PluginExecution exec = (PluginExecution) i.next(); + if ( executionMap.containsKey( exec.getId() ) ) { - PluginExecution exec = (PluginExecution) i.next(); - - if ( executionMap.containsKey( exec.getId() ) ) - { - throw new IllegalStateException( "You cannot have two plugin executions with the same (or missing) elements.\nOffending execution\n\nId: \'" + exec.getId() + "\'\nPlugin:\'" + getKey() + "\'\n\n" ); - } - - executionMap.put( exec.getId(), exec ); + throw new IllegalStateException( "You cannot have two plugin executions with the same (or missing) elements.\nOffending execution\n\nId: \'" + exec.getId() + "\'\nPlugin:\'" + getKey() + "\'\n\n" ); } + executionMap.put( exec.getId(), exec ); } } - return executionMap; } @@ -2318,7 +2254,7 @@ */ public String getKey() { - return constructKey( groupId, artifactId ); + return constructKey( getGroupId(), getArtifactId() ); } /** @@ -2432,7 +2368,7 @@ - + DependencyManagement 4.0.0+ Section for management of default dependency information for use in a group of @@ -2458,7 +2394,7 @@ Section for management of default plugin information for use in a group of POMs. - + Reporting 4.0.0+ Section for management of reports and their configuration. @@ -2505,45 +2441,9 @@ reportPluginMap; - - /** - * Reset the reportPluginMap field to null - */ - public synchronized void flushReportPluginMap() - { - this.reportPluginMap = null; + return ( getExcludeDefaults() != null ) ? Boolean.parseBoolean( getExcludeDefaults() ) : false; } - /** - * @return a Map of plugins field with ReportPlugin#getKey() as key - * @see org.apache.maven.model.ReportPlugin#getKey() - */ - public synchronized java.util.Map getReportPluginsAsMap() - { - if ( reportPluginMap == null ) - { - reportPluginMap = new java.util.LinkedHashMap(); - if ( getPlugins() != null ) - { - for ( java.util.Iterator it = getPlugins().iterator(); it.hasNext(); ) - { - ReportPlugin reportPlugin = (ReportPlugin) it.next(); - reportPluginMap.put( reportPlugin.getKey(), reportPlugin ); - } - } - } - - return reportPluginMap; - } ]]> @@ -2621,7 +2521,7 @@ - + Activation 4.0.0+ The conditions within the build runtime environment which will trigger the @@ -2690,7 +2590,7 @@ --> - + ActivationProperty 4.0.0+ This is the property specification used to activate a profile. If the value field @@ -2712,7 +2612,7 @@ - + ActivationOS 4.0.0+ This is an activator which will detect an operating system's attributes in order @@ -2756,7 +2656,7 @@ - + ActivationFile 4.0.0+ missing value @@ -2899,7 +2799,7 @@ */ public String getKey() { - return constructKey( groupId, artifactId ); + return constructKey( getGroupId(), getArtifactId() ); } /** @@ -2916,7 +2816,7 @@ - + ReportSet 4.0.0+ ConfigurationContainer @@ -2957,7 +2857,7 @@ - + Prerequisites 4.0.0+ Describes the prerequisites a project can have. @@ -2980,7 +2880,7 @@ - + Relocation 4.0.0+ Describes where an artifact has moved to. If any of the values are omitted, it is @@ -3012,7 +2912,7 @@ - + Extension 4.0.0+ Describes a build extension to utilise. @@ -3096,7 +2996,7 @@ - + InputLocation 4.0.0+ @@ -3118,7 +3018,7 @@ - + InputSource 4.0.0+ diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm new file mode 100644 index 000000000000..c57c798b7ace --- /dev/null +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -0,0 +1,403 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.model" ) +#set ( $package = "${basePackage}" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end + #end + #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "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 = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #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 +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable, InputLocationTracker +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.allFields ) + final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + #end + #if ( ! $class.superClass ) + final Map locations; + final InputLocation location; + #end + #foreach ( $field in $class.allFields ) + final InputLocation ${field.name}Location; + #end + + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name, + #end + Map locations, + InputLocation location, + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + InputLocation ${field.name}Location${sep} + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + ${field.name}, + #end + locations, + location, + #foreach ( $field in $inheritedFields ) + #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${field.name}Location${sep} + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.allFields ) + this.${field.name} = ${field.name}; + #end + #if ( ! $class.superClass ) + this.locations = locations; + this.location = location; + #end + #foreach ( $field in $class.allFields ) + this.${field.name}Location = ${field.name}Location; + #end + } + + #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 ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #end + #foreach ( $field in $class.allFields ) + #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 ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.allFields ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + public ${class.name} with${cap}( $type $field.name ) + { + return newBuilder( this ).${field.name}( $field.name ).build(); + } + #end + + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + public static Builder newBuilder() + { + return newBuilder( true ); + } + + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + #if ( ! $class.superClass ) + Map locations; + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.allFields ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.allFields ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + public Builder location( Object key, InputLocation location ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + return this; + } + + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); + InputLocation location = locations.remove( "" ); + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + #end + #foreach ( $field in $allFields ) + #if ( $field.type == "java.util.List" ) + ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() ), + #elseif ( $field.type == "java.util.Properties" ) + new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) ), + #elseif ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} ), + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ), + #end + #end + Collections.unmodifiableMap( locations ), + location != null ? location : ( base != null ? base.location : null ), + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end + ); + } + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml new file mode 100644 index 000000000000..4d716baf7e92 --- /dev/null +++ b/api/maven-api-settings/pom.xml @@ -0,0 +1,101 @@ + + + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-settings + + Maven Settings + Maven Settings model. + + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + attach-mdo + + attach-artifact + + + + + src/main/mdo/settings.mdo + mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + 2.0.0 + + src/main/mdo/settings.mdo + + + + + + + + modello + + velocity + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + + + + + diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java new file mode 100644 index 000000000000..49cdfebf5dd3 --- /dev/null +++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java @@ -0,0 +1,120 @@ +package org.apache.maven.api.settings; + +/* + * 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. + */ + +import java.util.Map; +import java.util.Properties; +import java.util.function.BiFunction; +import java.util.function.Function; + +class ROProperties extends Properties +{ + ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object remove( Object key ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void putAll( Map t ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void clear() + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object replace( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + +} diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm new file mode 100644 index 000000000000..19bba531bf0d --- /dev/null +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -0,0 +1,331 @@ +#* + 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. +*# +#set ( $package = "org.apache.maven.api.settings" ) +# +#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.getFields($version) ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end + #end + #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "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 = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #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 +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + #end + + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name${sep} + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${field.name}${sep} + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = ${field.name}; + #end + } + + #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 ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #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 ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + public ${class.name} with${cap}( $type $field.name ) + { + return newBuilder( this ).${field.name}( $field.name ).build(); + } + #end + + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + public static Builder newBuilder() + { + return newBuilder( true ); + } + + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.getFields($version) ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + #end + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + #if ( $field.type == "java.util.List" ) + ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() )${sep} + #elseif ( $field.type == "java.util.Properties" ) + new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) )${sep} + #elseif ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} + #end + #end + ); + } + } + + #foreach ( $cs in $class.allCodeSegments ) +$cs.code + #end +} + #end +#end diff --git a/maven-settings/src/main/mdo/settings.mdo b/api/maven-api-settings/src/main/mdo/settings.mdo similarity index 99% rename from maven-settings/src/main/mdo/settings.mdo rename to api/maven-api-settings/src/main/mdo/settings.mdo index 4500560ca601..6a5757bb89dd 100644 --- a/maven-settings/src/main/mdo/settings.mdo +++ b/api/maven-api-settings/src/main/mdo/settings.mdo @@ -654,9 +654,9 @@ StringBuilder sb = new StringBuilder( 128 ); sb.append( "Mirror[" ); sb.append( "id=" ).append( this.getId() ); - sb.append( ",mirrorOf=" ).append( mirrorOf ); - sb.append( ",url=" ).append( this.url ); - sb.append( ",name=" ).append( this.name ); + sb.append( ",mirrorOf=" ).append( this.getMirrorOf() ); + sb.append( ",url=" ).append( this.getUrl() ); + sb.append( ",name=" ).append( this.getName() ); if ( isBlocked() ) { sb.append( ",blocked" ); @@ -874,14 +874,11 @@ public boolean equals( Object obj ) { RepositoryBase other = (RepositoryBase) obj; - boolean retValue = false; - - if ( id != null ) + if ( this.getId() != null ) { - retValue = id.equals( other.id ); + retValue = this.getId().equals( other.getId() ); } - return retValue; } ]]> diff --git a/api/maven-api-settings/src/site/apt/index.apt b/api/maven-api-settings/src/site/apt/index.apt new file mode 100644 index 000000000000..2b42ccd16a36 --- /dev/null +++ b/api/maven-api-settings/src/site/apt/index.apt @@ -0,0 +1,36 @@ +~~ 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. + + ----- + Introduction + ----- + Vincent Siveton + ----- + 2006-11-04 + ----- + +Maven Settings Model + + This is strictly the model for Maven settings. + + The following are generated from this model: + + * {{{./apidocs/index.html}Java sources}} with Reader and Writers for the Xpp3 XML parser + + * A {{{./settings.html}Descriptor Reference}} + + * An {{{https://maven.apache.org/xsd/settings-1.2.0.xsd}XSD}} diff --git a/api/maven-api-settings/src/site/site.xml b/api/maven-api-settings/src/site/site.xml new file mode 100644 index 000000000000..e475330c4063 --- /dev/null +++ b/api/maven-api-settings/src/site/site.xml @@ -0,0 +1,38 @@ + + + + + + + ${project.scm.url} + + +

+ + + + + + + + + + \ No newline at end of file diff --git a/api/maven-api-toolchain/pom.xml b/api/maven-api-toolchain/pom.xml new file mode 100644 index 000000000000..a179bbcdf621 --- /dev/null +++ b/api/maven-api-toolchain/pom.xml @@ -0,0 +1,102 @@ + + + + + + + maven-api + org.apache.maven + 4.0.0-alpha-1-SNAPSHOT + + 4.0.0 + + maven-api-toolchain + + Maven Toolchain Model + Maven Toolchain model. + + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + + + + + org.codehaus.mojo + build-helper-maven-plugin + 3.2.0 + + + attach-mdo + + attach-artifact + + + + + src/main/mdo/toolchains.mdo + mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + 1.1.0 + + src/main/mdo/toolchains.mdo + + + + + + + + modello + + velocity + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + + + + + diff --git a/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java b/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java new file mode 100644 index 000000000000..9ae6c6d4c82b --- /dev/null +++ b/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java @@ -0,0 +1,120 @@ +package org.apache.maven.api.toolchain; + +/* + * 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. + */ + +import java.util.Map; +import java.util.Properties; +import java.util.function.BiFunction; +import java.util.function.Function; + +class ROProperties extends Properties +{ + ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object remove( Object key ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void putAll( Map t ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void clear() + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object replace( Object key, Object value ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw new UnsupportedOperationException( "Properties are read-only" ); + } + +} diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm new file mode 100644 index 000000000000..b3bdc9e25365 --- /dev/null +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -0,0 +1,332 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.toolchain" ) +#set ( $package = "$basePackage" ) +# +#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.getFields($version) ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end + #end + #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "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 = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #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 +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + #end + + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name${sep} + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${field.name}${sep} + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = ${field.name}; + #end + } + + #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 ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #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 ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + public ${class.name} with${cap}( $type $field.name ) + { + return newBuilder( this ).${field.name}( $field.name ).build(); + } + #end + + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + public static Builder newBuilder() + { + return newBuilder( true ); + } + + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.getFields($version) ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + #end + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + #if ( $field.type == "java.util.List" ) + ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() )${sep} + #elseif ( $field.type == "java.util.Properties" ) + new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) )${sep} + #elseif ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} + #end + #end + ); + } + } + + #foreach ( $cs in $class.allCodeSegments ) +$cs.code + #end +} + #end +#end diff --git a/maven-toolchain-model/src/main/mdo/toolchains.mdo b/api/maven-api-toolchain/src/main/mdo/toolchains.mdo similarity index 98% rename from maven-toolchain-model/src/main/mdo/toolchains.mdo rename to api/maven-api-toolchain/src/main/mdo/toolchains.mdo index 29f742ccaa8f..7090b9468640 100644 --- a/maven-toolchain-model/src/main/mdo/toolchains.mdo +++ b/api/maven-api-toolchain/src/main/mdo/toolchains.mdo @@ -189,8 +189,8 @@ { int result = 17; - result = 37 * result + ( type != null ? type.hashCode() : 0 ); - result = 37 * result + ( provides != null ? provides.hashCode() : 0 ); + result = 37 * result + ( getType() != null ? getType().hashCode() : 0 ); + result = 37 * result + ( getProvides() != null ? getProvides().hashCode() : 0 ); return result; } //-- int hashCode() diff --git a/api/maven-api-xml/pom.xml b/api/maven-api-xml/pom.xml new file mode 100644 index 000000000000..37379006d5c5 --- /dev/null +++ b/api/maven-api-xml/pom.xml @@ -0,0 +1,40 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + maven-api-xml + Apache Maven API XML + + + + org.apache.maven + maven-api-meta + 4.0.0-alpha-1-SNAPSHOT + + + + diff --git a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java new file mode 100644 index 000000000000..eade36e995de --- /dev/null +++ b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java @@ -0,0 +1,122 @@ +package org.apache.maven.api.xml; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.ThreadSafe; + +@ThreadSafe @Immutable +public interface Dom +{ + + String CHILDREN_COMBINATION_MODE_ATTRIBUTE = "combine.children"; + + String CHILDREN_COMBINATION_MERGE = "merge"; + + String CHILDREN_COMBINATION_APPEND = "append"; + + /** + * This default mode for combining children DOMs during merge means that where element names match, the process will + * try to merge the element data, rather than putting the dominant and recessive elements (which share the same + * element name) as siblings in the resulting DOM. + */ + String DEFAULT_CHILDREN_COMBINATION_MODE = CHILDREN_COMBINATION_MERGE; + + String SELF_COMBINATION_MODE_ATTRIBUTE = "combine.self"; + + String SELF_COMBINATION_OVERRIDE = "override"; + + String SELF_COMBINATION_MERGE = "merge"; + + String SELF_COMBINATION_REMOVE = "remove"; + + /** + * This default mode for combining a DOM node during merge means that where element names match, the process will + * try to merge the element attributes and values, rather than overriding the recessive element completely with the + * dominant one. This means that wherever the dominant element doesn't provide the value or a particular attribute, + * that value or attribute will be set from the recessive DOM node. + */ + String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE; + + @Nonnull + String getName(); + + @Nullable + String getValue(); + + @Nonnull + Map getAttributes(); + + @Nullable + String getAttribute( @Nonnull String name ); + + @Nonnull + List getChildren(); + + @Nullable + Dom getChild( String name ); + + @Nullable + Object getInputLocation(); + + default Dom merge( @Nullable Dom source ) + { + return merge( source, (Boolean) null ); + } + + Dom merge( @Nullable Dom source, @Nullable Boolean childMergeOverride ); + + Dom clone(); + + /** + * Merge recessive into dominant and return either {@code dominant} + * with merged information or a clone of {@code recessive} if + * {@code dominant} is {@code null}. + * + * @param dominant the node + * @param recessive if {@code null}, nothing will happen + * @return the merged node + */ + @Nullable + static Dom merge( @Nullable Dom dominant, @Nullable Dom recessive ) + { + return merge( dominant, recessive, null ); + } + + @Nullable + static Dom merge( @Nullable Dom dominant, @Nullable Dom recessive, @Nullable Boolean childMergeOverride ) + { + if ( recessive == null ) + { + return dominant; + } + if ( dominant == null ) + { + return recessive; + } + return dominant.merge( recessive, childMergeOverride ); + } + +} diff --git a/api/modello-plugin-velocity/pom.xml b/api/modello-plugin-velocity/pom.xml new file mode 100644 index 000000000000..55f1cf106090 --- /dev/null +++ b/api/modello-plugin-velocity/pom.xml @@ -0,0 +1,94 @@ + + + + 4.0.0 + + + org.apache.maven + maven-api + 4.0.0-alpha-1-SNAPSHOT + + + modello-plugin-velocity + maven-plugin + Modello Velocity Plugin + + Modello Velocity Plugin generates custom templates. + + + + 3.6.4 + 3.8.5 + + + + + org.apache.maven.plugin-tools + maven-plugin-annotations + ${mavenPluginTools} + provided + + + org.apache.maven + maven-plugin-api + ${maven} + provided + + + * + * + + + + + org.apache.maven + maven-core + ${maven} + provided + + + * + * + + + + + org.codehaus.modello + modello-maven-plugin + 2.0.0 + + + org.apache.velocity + velocity-engine-core + 2.3 + + + org.codehaus.modello + modello-core + 2.0.0 + + + org.codehaus.modello + modello-plugin-xml + 2.0.0 + + + + diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingOutputStream.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingOutputStream.java new file mode 100644 index 000000000000..d88955d711ee --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingOutputStream.java @@ -0,0 +1,170 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.OutputStream; +import java.nio.Buffer; +import java.nio.ByteBuffer; +import java.nio.channels.FileChannel; +import java.nio.file.Path; +import java.nio.file.StandardOpenOption; +import java.util.Objects; + +/** + * Caching OutputStream to avoid overwriting a file with + * the same content. + */ +public class CachingOutputStream extends OutputStream +{ + private final Path path; + private FileChannel channel; + private ByteBuffer readBuffer; + private ByteBuffer writeBuffer; + private boolean modified; + + public CachingOutputStream( File path ) throws IOException + { + this( Objects.requireNonNull( path ).toPath() ); + } + + public CachingOutputStream( Path path ) throws IOException + { + this( path, 32 * 1024 ); + } + + public CachingOutputStream( Path path, int bufferSize ) throws IOException + { + this.path = Objects.requireNonNull( path ); + this.channel = FileChannel.open( path, + StandardOpenOption.READ, StandardOpenOption.WRITE, StandardOpenOption.CREATE ); + this.readBuffer = ByteBuffer.allocate( bufferSize ); + this.writeBuffer = ByteBuffer.allocate( bufferSize ); + } + + @Override + public void write( int b ) throws IOException + { + if ( writeBuffer.remaining() < 1 ) + { + ( ( Buffer ) writeBuffer ).flip(); + flushBuffer( writeBuffer ); + ( ( Buffer ) writeBuffer ).clear(); + } + writeBuffer.put( ( byte ) b ); + } + + @Override + public void write( byte[] b ) throws IOException + { + write( b, 0, b.length ); + } + + @Override + public void write( byte[] b, int off, int len ) throws IOException + { + if ( writeBuffer.remaining() < len ) + { + ( ( Buffer ) writeBuffer ).flip(); + flushBuffer( writeBuffer ); + ( ( Buffer ) writeBuffer ).clear(); + } + int capacity = writeBuffer.capacity(); + while ( len >= capacity ) + { + flushBuffer( ByteBuffer.wrap( b, off, capacity ) ); + off += capacity; + len -= capacity; + } + if ( len > 0 ) + { + writeBuffer.put( b, off, len ); + } + } + + @Override + public void flush() throws IOException + { + ( ( Buffer ) writeBuffer ).flip(); + flushBuffer( writeBuffer ); + ( ( Buffer ) writeBuffer ).clear(); + super.flush(); + } + + private void flushBuffer( ByteBuffer writeBuffer ) throws IOException + { + if ( modified ) + { + channel.write( writeBuffer ); + } + else + { + int len = writeBuffer.remaining(); + ByteBuffer readBuffer; + if ( this.readBuffer.capacity() >= len ) + { + readBuffer = this.readBuffer; + ( ( Buffer ) readBuffer ).clear(); + } + else + { + readBuffer = ByteBuffer.allocate( len ); + } + while ( len > 0 ) + { + int read = channel.read( readBuffer ); + if ( read <= 0 ) + { + modified = true; + channel.position( channel.position() - readBuffer.position() ); + channel.write( writeBuffer ); + return; + } + len -= read; + } + ( ( Buffer ) readBuffer ).flip(); + if ( readBuffer.compareTo( writeBuffer ) != 0 ) + { + modified = true; + channel.position( channel.position() - readBuffer.remaining() ); + channel.write( writeBuffer ); + } + } + } + + @Override + public void close() throws IOException + { + flush(); + long position = channel.position(); + if ( position != channel.size() ) + { + modified = true; + channel.truncate( position ); + } + channel.close(); + } + + public boolean isModified() + { + return modified; + } +} \ No newline at end of file diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingWriter.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingWriter.java new file mode 100644 index 000000000000..081cbbf08592 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/CachingWriter.java @@ -0,0 +1,62 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.OutputStreamWriter; +import java.nio.charset.Charset; +import java.nio.file.Path; +import java.util.Objects; + +/** + * Caching Writer to avoid overwriting a file with + * the same content. + */ +public class CachingWriter extends OutputStreamWriter +{ + private final CachingOutputStream cos; + + public CachingWriter( File path, Charset charset ) throws IOException + { + this( Objects.requireNonNull( path ).toPath(), charset ); + } + + public CachingWriter( Path path, Charset charset ) throws IOException + { + this( path, charset, 32 * 1024 ); + } + + public CachingWriter( Path path, Charset charset, int bufferSize ) throws IOException + { + this( new CachingOutputStream( path, bufferSize ), charset ); + } + + private CachingWriter( CachingOutputStream outputStream, Charset charset ) throws IOException + { + super( outputStream, charset ); + this.cos = outputStream; + } + + public boolean isModified() + { + return cos.isModified(); + } +} \ No newline at end of file diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java new file mode 100644 index 000000000000..6e0072e56ef9 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java @@ -0,0 +1,110 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.io.File; +import java.lang.reflect.Field; +import java.lang.reflect.Modifier; +import java.util.List; +import java.util.Objects; +import java.util.Properties; + +import org.apache.maven.plugins.annotations.LifecyclePhase; +import org.apache.maven.plugins.annotations.Mojo; +import org.apache.maven.plugins.annotations.Parameter; +import org.codehaus.modello.maven.AbstractModelloGeneratorMojo; +import org.codehaus.modello.model.ModelField; + +/** + * Creates an XML schema from the model. + * + * @author Brett Porter + */ +@Mojo( name = "velocity", defaultPhase = LifecyclePhase.GENERATE_SOURCES, threadSafe = true ) +public class ModelloVelocityMojo + extends AbstractModelloGeneratorMojo +{ + /** + * The output directory of the generated XML Schema. + */ + @Parameter( defaultValue = "${project.build.directory}/generated-sources/modello", required = true ) + private File outputDirectory; + + @Parameter + private List templates; + + protected String getGeneratorType() + { + return "velocity"; + } + + protected void customizeParameters( Properties parameters ) + { + try + { + Field field = ModelField.class.getDeclaredField( "PRIMITIVE_TYPES" ); + field.setAccessible( true ); + unsetFinal( field ); + field.set( null, new String[] { "boolean", "Boolean", "char", "Character", "byte", + "Byte", "short", "Short", "int", "Integer", "long", "Long", "float", "Float", + "double", "Double", "String", "Date", "DOM", "java.nio.file.Path" } ); + + super.customizeParameters( parameters ); + parameters.put( "basedir", Objects.requireNonNull( getBasedir(), "basedir is null" ) ); + parameters.put( VelocityGenerator.VELOCITY_TEMPLATES, String.join( ",", templates ) ); + } + catch ( Throwable e ) + { + throw new RuntimeException( e ); + } + } + + private void unsetFinal( Field field ) throws IllegalAccessException, NoSuchFieldException + { +// TODO: on jdk >= 12, accessing Field.modifiers fail, need to check with VarHandle or adds an open module +// try +// { + Field modifiersField = Field.class.getDeclaredField( "modifiers" ); + modifiersField.setAccessible( true ); + modifiersField.setInt( field, field.getModifiers() & ~Modifier.FINAL ); +// } +// catch ( Throwable t ) +// { +// MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup()); +// VarHandle modifiers = lookup.findVarHandle( Field.class, "modifiers", int.class ); +// modifiers.set( field, field.getModifiers() & ~Modifier.FINAL ); +// } + } + + protected boolean producesCompilableResult() + { + return true; + } + + public File getOutputDirectory() + { + return outputDirectory; + } + + public void setOutputDirectory( File outputDirectory ) + { + this.outputDirectory = outputDirectory; + } +} diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java new file mode 100644 index 000000000000..95677021ce03 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java @@ -0,0 +1,285 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.Writer; +import java.nio.charset.StandardCharsets; +import java.nio.file.Files; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; +import java.util.Map; +import java.util.Properties; + +import org.apache.velocity.Template; +import org.apache.velocity.VelocityContext; +import org.apache.velocity.runtime.RuntimeInstance; +import org.codehaus.modello.ModelloException; +import org.codehaus.modello.ModelloParameterConstants; +import org.codehaus.modello.ModelloRuntimeException; +import org.codehaus.modello.model.Model; +import org.codehaus.modello.model.ModelAssociation; +import org.codehaus.modello.model.ModelClass; +import org.codehaus.modello.model.ModelField; +import org.codehaus.modello.model.Version; +import org.codehaus.modello.plugin.AbstractModelloGenerator; +import org.codehaus.modello.plugin.ModelloGenerator; +import org.codehaus.modello.plugins.xml.metadata.XmlAssociationMetadata; +import org.codehaus.modello.plugins.xml.metadata.XmlClassMetadata; +import org.codehaus.modello.plugins.xml.metadata.XmlFieldMetadata; +import org.codehaus.plexus.component.annotations.Component; +import org.codehaus.plexus.util.StringUtils; + +@Component( role = ModelloGenerator.class, hint = "velocity" ) +public class VelocityGenerator + extends AbstractModelloGenerator +{ + public static final String VELOCITY_TEMPLATES = "modello.velocity.template"; + + @Override + public void generate( Model model, Properties parameters ) throws ModelloException + { + try + { + String templates = getParameter( parameters, VELOCITY_TEMPLATES ); + String output = getParameter( parameters, ModelloParameterConstants.OUTPUT_DIRECTORY ); + + Properties props = new Properties(); + props.put( "resource.loader.file.path", getParameter( parameters, "basedir" ) ); + RuntimeInstance velocity = new RuntimeInstance(); + velocity.init( props ); + + VelocityContext context = new VelocityContext(); + for ( Map.Entry prop : parameters.entrySet() ) + { + context.put( prop.getKey().toString(), prop.getValue() ); + } + Version version = new Version( getParameter( parameters, ModelloParameterConstants.VERSION ) ); + context.put( "version", version ); + context.put( "model", model ); + context.put( "Helper", new Helper( version ) ); + + for ( String templatePath : templates.split( "," ) ) + { + Template template = velocity.getTemplate( templatePath ); + + try ( Writer w = new RedirectingWriter( Paths.get( output ) ) ) + { + template.merge( context, w ); + } + } + } + catch ( Exception e ) + { + throw new ModelloException( "Unable to run velocity template", e ); + } + + } + + public static class Helper + { + private final Version version; + + public Helper( Version version ) + { + this.version = version; + } + + public String capitalise( String str ) + { + return StringUtils.isEmpty( str ) ? str : Character.toTitleCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + public String uncapitalise( String str ) + { + return StringUtils.isEmpty( str ) ? str : Character.toLowerCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + public String singular( String str ) + { + return AbstractModelloGenerator.singular( str ); + } + + public List ancestors( ModelClass clazz ) + { + List ancestors = new ArrayList<>(); + for ( ModelClass cl = clazz; cl != null; cl = cl.getSuperClass() != null + ? cl.getModel().getClass( cl.getSuperClass(), version ) : null ) + { + ancestors.add( 0, cl ); + } + return ancestors; + } + + public XmlClassMetadata xmlClassMetadata( ModelClass clazz ) + { + return (XmlClassMetadata) clazz.getMetadata( XmlClassMetadata.ID ); + } + + public XmlFieldMetadata xmlFieldMetadata( ModelField field ) + { + return (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); + } + + public XmlAssociationMetadata xmAssociationMetadata( ModelField field ) + { + return (XmlAssociationMetadata) ( ( ModelAssociation ) field ) + .getAssociationMetadata( XmlAssociationMetadata.ID ); + } + + public boolean isFlatItems( ModelField field ) + { + return field instanceof ModelAssociation && xmAssociationMetadata( field ).isFlatItems(); + } + + public List xmlFields( ModelClass modelClass ) + { + List classes = new ArrayList<>(); + // get the full inheritance + while ( modelClass != null ) + { + classes.add( modelClass ); + String superClass = modelClass.getSuperClass(); + if ( superClass != null ) + { + // superClass can be located outside (not generated by modello) + modelClass = modelClass.getModel().getClass( superClass, version, true ); + } + else + { + modelClass = null; + } + } + List fields = new ArrayList<>(); + for ( int i = classes.size() - 1; i >= 0; i-- ) + { + modelClass = classes.get( i ); + Iterator parentIter = fields.iterator(); + fields = new ArrayList<>(); + for ( ModelField field : modelClass.getFields( version ) ) + { + XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); + if ( xmlFieldMetadata.isTransient() ) + { + // just ignore xml.transient fields + continue; + } + if ( xmlFieldMetadata.getInsertParentFieldsUpTo() != null ) + { + // insert fields from parent up to the specified field + boolean found = false; + while ( !found && parentIter.hasNext() ) + { + ModelField parentField = parentIter.next(); + fields.add( parentField ); + found = parentField.getName().equals( xmlFieldMetadata.getInsertParentFieldsUpTo() ); + } + if ( !found ) + { + // interParentFieldsUpTo not found + throw new ModelloRuntimeException( "parent field not found: class " + + modelClass.getName() + " xml.insertParentFieldUpTo='" + + xmlFieldMetadata.getInsertParentFieldsUpTo() + "'" ); + } + } + fields.add( field ); + } + // add every remaining fields from parent class + while ( parentIter.hasNext() ) + { + fields.add( parentIter.next() ); + } + } + return fields; + } + } + + static class RedirectingWriter extends Writer + { + Path dir; + StringBuilder sb = new StringBuilder(); + Writer current; + + RedirectingWriter( Path dir ) + { + this.dir = dir; + } + + @Override + public void write( char[] cbuf, int off, int len ) throws IOException + { + for ( int i = 0; i < len; i++ ) + { + if ( cbuf[ off + i] == '\n' ) + { + writeLine( sb.toString() ); + sb.setLength( 0 ); + } + else + { + sb.append( cbuf[ off + i ] ); + } + } + } + + protected void writeLine( String line ) throws IOException + { + if ( line.startsWith( "#MODELLO-VELOCITY#REDIRECT " ) ) + { + String file = line.substring( "#MODELLO-VELOCITY#REDIRECT ".length() ); + if ( current != null ) + { + current.close(); + } + Path out = dir.resolve( file ); + Files.createDirectories( out.getParent() ); + current = new CachingWriter( out, StandardCharsets.UTF_8 ); + } + else if ( current != null ) + { + current.write( line ); + current.write( "\n" ); + } + } + + @Override + public void flush() throws IOException + { + if ( current != null ) + { + current.flush(); + } + } + + @Override + public void close() throws IOException + { + if ( current != null ) + { + current.close(); + current = null; + } + } + } + +} diff --git a/api/modello-plugin-velocity/src/main/resources/META-INF/plexus/components.xml b/api/modello-plugin-velocity/src/main/resources/META-INF/plexus/components.xml new file mode 100644 index 000000000000..ed745b2fc461 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/resources/META-INF/plexus/components.xml @@ -0,0 +1,31 @@ + + + + + + + + org.codehaus.modello.plugin.ModelloGenerator + velocity + org.codehaus.modello.plugin.velocity.VelocityGenerator + per-lookup + + + diff --git a/api/pom.xml b/api/pom.xml new file mode 100644 index 000000000000..108978e4be01 --- /dev/null +++ b/api/pom.xml @@ -0,0 +1,43 @@ + + + + 4.0.0 + + + org.apache.maven + maven + 4.0.0-alpha-1-SNAPSHOT + + + maven-api + Apache Maven API + pom + + + modello-plugin-velocity + maven-api-meta + maven-api-xml + maven-api-model + maven-api-settings + maven-api-toolchain + maven-api-core + + + diff --git a/build/checkstyle-suppressions.xml b/build/checkstyle-suppressions.xml index 78e9e3c05eeb..45702996fb5b 100644 --- a/build/checkstyle-suppressions.xml +++ b/build/checkstyle-suppressions.xml @@ -26,5 +26,4 @@ under the License. - diff --git a/maven-bom/pom.xml b/maven-bom/pom.xml index 4f9b6e370d3a..257eac644a4b 100644 --- a/maven-bom/pom.xml +++ b/maven-bom/pom.xml @@ -94,6 +94,11 @@ under the License. maven-model ${project.version} + + org.apache.maven + maven-api-core + ${project.version} + org.apache.maven maven-model-builder diff --git a/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java b/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java index 5f7957e7063e..2bfefbec4c0a 100644 --- a/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java +++ b/maven-compat/src/main/java/org/apache/maven/artifact/manager/DefaultWagonManager.java @@ -85,9 +85,9 @@ public AuthenticationInfo getAuthenticationInfo( String id ) { if ( id.equalsIgnoreCase( server.getId() ) ) { - SettingsDecryptionResult result = - settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( server ) ); - server = result.getServer(); + SettingsDecryptionResult result = settingsDecrypter.decrypt( + new DefaultSettingsDecryptionRequest( server.getDelegate() ) ); + server = new Server( result.getServer() ); AuthenticationInfo authInfo = new AuthenticationInfo(); authInfo.setUserName( server.getUsername() ); @@ -124,9 +124,9 @@ public ProxyInfo getProxy( String protocol ) { if ( proxy.isActive() && protocol.equalsIgnoreCase( proxy.getProtocol() ) ) { - SettingsDecryptionResult result = - settingsDecrypter.decrypt( new DefaultSettingsDecryptionRequest( proxy ) ); - proxy = result.getProxy(); + SettingsDecryptionResult result = settingsDecrypter.decrypt( + new DefaultSettingsDecryptionRequest( proxy.getDelegate() ) ); + proxy = new Proxy( result.getProxy() ); ProxyInfo proxyInfo = new ProxyInfo(); proxyInfo.setHost( proxy.getHost() ); diff --git a/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java b/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java index 11dc0a332229..bc4b7dae57d7 100644 --- a/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java +++ b/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java @@ -32,10 +32,12 @@ import org.codehaus.plexus.logging.Logger; import java.util.ArrayList; +import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; +import java.util.stream.Collectors; /** * DefaultProfileManager @@ -185,7 +187,10 @@ public List getActiveProfiles() final List errors = new ArrayList<>(); - List profiles = profileSelector.getActiveProfiles( profilesById.values(), context, req -> + Collection values = profilesById.values(); + List list = + values.stream().map( Profile::getDelegate ).collect( Collectors.toList() ); + List profiles = profileSelector.getActiveProfiles( list, context, req -> { if ( !ModelProblem.Severity.WARNING.equals( req.getSeverity() ) ) { @@ -198,7 +203,7 @@ public List getActiveProfiles() throw errors.get( 0 ); } - return profiles; + return Profile.profileToApiV3( profiles ); } /* (non-Javadoc) diff --git a/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java b/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java index 154176eecf76..17f8592ec8bd 100644 --- a/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java +++ b/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java @@ -145,7 +145,7 @@ private static Repository convertFromProfileXmlRepository( org.apache.maven.prof private static org.apache.maven.model.RepositoryPolicy convertRepositoryPolicy( RepositoryPolicy profileXmlRepo ) { org.apache.maven.model.RepositoryPolicy policy = new org.apache.maven.model.RepositoryPolicy(); - policy.setEnabled( profileXmlRepo.isEnabled() ); + policy.setEnabled( Boolean.toString( profileXmlRepo.isEnabled() ) ); policy.setUpdatePolicy( profileXmlRepo.getUpdatePolicy() ); policy.setChecksumPolicy( profileXmlRepo.getChecksumPolicy() ); return policy; diff --git a/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java b/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java index 6b378b7af157..2c94f7a6f651 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java +++ b/maven-compat/src/main/java/org/apache/maven/project/ModelUtils.java @@ -19,19 +19,10 @@ * under the License. */ -import java.util.ArrayList; -import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; -import java.util.Map; -import java.util.TreeMap; -import org.apache.maven.model.Dependency; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.Repository; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** @deprecated */ @Deprecated @@ -54,309 +45,24 @@ public final class ModelUtils public static void mergePluginLists( PluginContainer childContainer, PluginContainer parentContainer, boolean handleAsInheritance ) { - if ( ( childContainer == null ) || ( parentContainer == null ) ) - { - // nothing to do. - return; - } - - List parentPlugins = parentContainer.getPlugins(); - - if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() ) - { - parentPlugins = new ArrayList<>( parentPlugins ); - - // If we're processing this merge as an inheritance, we have to build up a list of - // plugins that were considered for inheritance. - if ( handleAsInheritance ) - { - for ( Iterator it = parentPlugins.iterator(); it.hasNext(); ) - { - Plugin plugin = it.next(); - - String inherited = plugin.getInherited(); - - if ( ( inherited != null ) && !Boolean.parseBoolean( inherited ) ) - { - it.remove(); - } - } - } - - List assembledPlugins = new ArrayList<>(); - - Map childPlugins = childContainer.getPluginsAsMap(); - - for ( Plugin parentPlugin : parentPlugins ) - { - String parentInherited = parentPlugin.getInherited(); - - // only merge plugin definition from the parent if at least one - // of these is true: - // 1. we're not processing the plugins in an inheritance-based merge - // 2. the parent's flag is not set - // 3. the parent's flag is set to true - if ( !handleAsInheritance || ( parentInherited == null ) - || Boolean.parseBoolean( parentInherited ) ) - { - Plugin childPlugin = childPlugins.get( parentPlugin.getKey() ); - - if ( ( childPlugin != null ) && !assembledPlugins.contains( childPlugin ) ) - { - mergePluginDefinitions( childPlugin, parentPlugin, handleAsInheritance ); - - // fix for MNG-2221 (assembly cache was not being populated for later reference): - assembledPlugins.add( childPlugin ); - } - - // if we're processing this as an inheritance-based merge, and - // the parent's flag is not set, then we need to - // clear the inherited flag in the merge result. - if ( handleAsInheritance && ( parentInherited == null ) ) - { - parentPlugin.unsetInheritanceApplied(); - } - } - - // very important to use the parentPlugins List, rather than parentContainer.getPlugins() - // since this list is a local one, and may have been modified during processing. - List results = - ModelUtils.orderAfterMerge( assembledPlugins, parentPlugins, childContainer.getPlugins() ); - - childContainer.setPlugins( results ); - - childContainer.flushPluginMap(); - } - } + throw new UnsupportedOperationException(); } public static List orderAfterMerge( List merged, List highPrioritySource, List lowPrioritySource ) { - List results = new ArrayList<>(); - - if ( !merged.isEmpty() ) - { - results.addAll( merged ); - } - - List missingFromResults = new ArrayList<>(); - - List> sources = new ArrayList<>(); - - sources.add( highPrioritySource ); - sources.add( lowPrioritySource ); - - for ( List source : sources ) - { - for ( Plugin item : source ) - { - if ( results.contains( item ) ) - { - if ( !missingFromResults.isEmpty() ) - { - int idx = results.indexOf( item ); - - if ( idx < 0 ) - { - idx = 0; - } - - results.addAll( idx, missingFromResults ); - - missingFromResults.clear(); - } - } - else - { - missingFromResults.add( item ); - } - } - - if ( !missingFromResults.isEmpty() ) - { - results.addAll( missingFromResults ); - - missingFromResults.clear(); - } - } - - return results; + throw new UnsupportedOperationException(); } public static void mergePluginDefinitions( Plugin child, Plugin parent, boolean handleAsInheritance ) { - if ( ( child == null ) || ( parent == null ) ) - { - // nothing to do. - return; - } - - if ( parent.isExtensions() ) - { - child.setExtensions( true ); - } - - if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) ) - { - child.setVersion( parent.getVersion() ); - } - - Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); - Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); - - childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); - - child.setConfiguration( childConfiguration ); - - child.setDependencies( mergeDependencyList( child.getDependencies(), parent.getDependencies() ) ); - - // from here to the end of the method is dealing with merging of the section. - String parentInherited = parent.getInherited(); - - boolean parentIsInherited = ( parentInherited == null ) || Boolean.parseBoolean( parentInherited ); - - List parentExecutions = parent.getExecutions(); - - if ( ( parentExecutions != null ) && !parentExecutions.isEmpty() ) - { - List mergedExecutions = new ArrayList<>(); - - Map assembledExecutions = new TreeMap<>(); - - Map childExecutions = child.getExecutionsAsMap(); - - for ( PluginExecution parentExecution : parentExecutions ) - { - String inherited = parentExecution.getInherited(); - - boolean parentExecInherited = - parentIsInherited && ( ( inherited == null ) || Boolean.parseBoolean( inherited ) ); - - if ( !handleAsInheritance || parentExecInherited ) - { - PluginExecution assembled = parentExecution; - - PluginExecution childExecution = childExecutions.get( parentExecution.getId() ); - - if ( childExecution != null ) - { - mergePluginExecutionDefinitions( childExecution, parentExecution ); - - assembled = childExecution; - } - else if ( handleAsInheritance && ( parentInherited == null ) ) - { - parentExecution.unsetInheritanceApplied(); - } - - assembledExecutions.put( assembled.getId(), assembled ); - mergedExecutions.add( assembled ); - } - } - - for ( PluginExecution childExecution : child.getExecutions() ) - { - if ( !assembledExecutions.containsKey( childExecution.getId() ) ) - { - mergedExecutions.add( childExecution ); - } - } - - child.setExecutions( mergedExecutions ); - - child.flushExecutionMap(); - } - - } - - private static void mergePluginExecutionDefinitions( PluginExecution child, PluginExecution parent ) - { - if ( child.getPhase() == null ) - { - child.setPhase( parent.getPhase() ); - } - - List parentGoals = parent.getGoals(); - List childGoals = child.getGoals(); - - List goals = new ArrayList<>(); - - if ( ( childGoals != null ) && !childGoals.isEmpty() ) - { - goals.addAll( childGoals ); - } - - if ( parentGoals != null ) - { - for ( String goal : parentGoals ) - { - if ( !goals.contains( goal ) ) - { - goals.add( goal ); - } - } - } - - child.setGoals( goals ); - - Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); - Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); - - childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); - - child.setConfiguration( childConfiguration ); - } - - public static List mergeRepositoryLists( List dominant, List recessive ) - { - - List repositories = new ArrayList<>( dominant ); - - for ( Repository repository : recessive ) - { - if ( !repositories.contains( repository ) ) - { - repositories.add( repository ); - } - } - - return repositories; + throw new UnsupportedOperationException(); } public static void mergeFilterLists( List childFilters, List parentFilters ) { - for ( String f : parentFilters ) - { - if ( !childFilters.contains( f ) ) - { - childFilters.add( f ); - } - } - } - - private static List mergeDependencyList( List child, List parent ) - { - Map depsMap = new LinkedHashMap<>(); - - if ( parent != null ) - { - for ( Dependency dependency : parent ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - if ( child != null ) - { - for ( Dependency dependency : child ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - return new ArrayList<>( depsMap.values() ); + throw new UnsupportedOperationException(); } } diff --git a/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java b/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java index 0113562cff29..b6dd90d81b91 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java +++ b/maven-compat/src/main/java/org/apache/maven/project/inheritance/DefaultModelInheritanceAssembler.java @@ -19,729 +19,38 @@ * under the License. */ -import java.util.ArrayList; -import java.util.LinkedHashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.StringTokenizer; -import java.util.TreeMap; - import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.DeploymentRepository; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Extension; import org.apache.maven.model.Model; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; -import org.apache.maven.project.ModelUtils; import org.codehaus.plexus.component.annotations.Component; -import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * DefaultModelInheritanceAssembler */ @Component( role = ModelInheritanceAssembler.class ) public class DefaultModelInheritanceAssembler - implements ModelInheritanceAssembler + implements ModelInheritanceAssembler { - public void assembleBuildInheritance( Build childBuild, Build parentBuild, boolean handleAsInheritance ) - { - // The build has been set but we want to step in here and fill in - // values that have not been set by the child. - - if ( childBuild.getSourceDirectory() == null ) - { - childBuild.setSourceDirectory( parentBuild.getSourceDirectory() ); - } - - if ( childBuild.getScriptSourceDirectory() == null ) - { - childBuild.setScriptSourceDirectory( parentBuild.getScriptSourceDirectory() ); - } - - if ( childBuild.getTestSourceDirectory() == null ) - { - childBuild.setTestSourceDirectory( parentBuild.getTestSourceDirectory() ); - } - - if ( childBuild.getOutputDirectory() == null ) - { - childBuild.setOutputDirectory( parentBuild.getOutputDirectory() ); - } - - if ( childBuild.getTestOutputDirectory() == null ) - { - childBuild.setTestOutputDirectory( parentBuild.getTestOutputDirectory() ); - } - - // Extensions are accumulated - mergeExtensionLists( childBuild, parentBuild ); - - if ( childBuild.getDirectory() == null ) - { - childBuild.setDirectory( parentBuild.getDirectory() ); - } - - if ( childBuild.getDefaultGoal() == null ) - { - childBuild.setDefaultGoal( parentBuild.getDefaultGoal() ); - } - - if ( childBuild.getFinalName() == null ) - { - childBuild.setFinalName( parentBuild.getFinalName() ); - } - - ModelUtils.mergeFilterLists( childBuild.getFilters(), parentBuild.getFilters() ); - - List resources = childBuild.getResources(); - if ( ( resources == null ) || resources.isEmpty() ) - { - childBuild.setResources( parentBuild.getResources() ); - } - - resources = childBuild.getTestResources(); - if ( ( resources == null ) || resources.isEmpty() ) - { - childBuild.setTestResources( parentBuild.getTestResources() ); - } - - // Plugins are aggregated if Plugin.inherit != false - ModelUtils.mergePluginLists( childBuild, parentBuild, handleAsInheritance ); - - // Plugin management :: aggregate - PluginManagement dominantPM = childBuild.getPluginManagement(); - PluginManagement recessivePM = parentBuild.getPluginManagement(); - - if ( ( dominantPM == null ) && ( recessivePM != null ) ) - { - // FIXME: Filter out the inherited == false stuff! - childBuild.setPluginManagement( recessivePM ); - } - else - { - ModelUtils.mergePluginLists( childBuild.getPluginManagement(), parentBuild.getPluginManagement(), false ); - } - } - - private void assembleScmInheritance( Model child, Model parent, String childPathAdjustment, boolean appendPaths ) - { - if ( parent.getScm() != null ) - { - Scm parentScm = parent.getScm(); - - Scm childScm = child.getScm(); - - if ( childScm == null ) - { - childScm = new Scm(); - - child.setScm( childScm ); - } - - if ( StringUtils.isEmpty( childScm.getConnection() ) && !StringUtils.isEmpty( parentScm.getConnection() ) ) - { - childScm.setConnection( - appendPath( parentScm.getConnection(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - - if ( StringUtils.isEmpty( childScm.getDeveloperConnection() ) - && !StringUtils.isEmpty( parentScm.getDeveloperConnection() ) ) - { - childScm - .setDeveloperConnection( appendPath( parentScm.getDeveloperConnection(), child.getArtifactId(), - childPathAdjustment, appendPaths ) ); - } - - if ( StringUtils.isEmpty( childScm.getUrl() ) && !StringUtils.isEmpty( parentScm.getUrl() ) ) - { - childScm.setUrl( - appendPath( parentScm.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - } - } - - public void copyModel( Model dest, Model source ) - { - assembleModelInheritance( dest, source, null, false ); - } - + @Override public void assembleModelInheritance( Model child, Model parent, String childPathAdjustment ) { - assembleModelInheritance( child, parent, childPathAdjustment, true ); + throw new UnsupportedOperationException(); } + @Override public void assembleModelInheritance( Model child, Model parent ) { - assembleModelInheritance( child, parent, null, true ); - } - - private void assembleModelInheritance( Model child, Model parent, String childPathAdjustment, boolean appendPaths ) - { - // cannot inherit from null parent. - if ( parent == null ) - { - return; - } - - // Group id - if ( child.getGroupId() == null ) - { - child.setGroupId( parent.getGroupId() ); - } - - // version - if ( child.getVersion() == null ) - { - // The parent version may have resolved to something different, so we take what we asked for... - // instead of - child.setVersion( parent.getVersion() ); - - if ( child.getParent() != null ) - { - child.setVersion( child.getParent().getVersion() ); - } - } - - // inceptionYear - if ( child.getInceptionYear() == null ) - { - child.setInceptionYear( parent.getInceptionYear() ); - } - - // url - if ( child.getUrl() == null ) - { - if ( parent.getUrl() != null ) - { - child.setUrl( appendPath( parent.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - else - { - child.setUrl( parent.getUrl() ); - } - } - - assembleDistributionInheritance( child, parent, childPathAdjustment, appendPaths ); - - // issueManagement - if ( child.getIssueManagement() == null ) - { - child.setIssueManagement( parent.getIssueManagement() ); - } - - // description - if ( child.getDescription() == null ) - { - child.setDescription( parent.getDescription() ); - } - - // Organization - if ( child.getOrganization() == null ) - { - child.setOrganization( parent.getOrganization() ); - } - - // Scm - assembleScmInheritance( child, parent, childPathAdjustment, appendPaths ); - - // ciManagement - if ( child.getCiManagement() == null ) - { - child.setCiManagement( parent.getCiManagement() ); - } - - // developers - if ( child.getDevelopers().size() == 0 ) - { - child.setDevelopers( parent.getDevelopers() ); - } - - // licenses - if ( child.getLicenses().size() == 0 ) - { - child.setLicenses( parent.getLicenses() ); - } - - // developers - if ( child.getContributors().size() == 0 ) - { - child.setContributors( parent.getContributors() ); - } - - // mailingLists - if ( child.getMailingLists().size() == 0 ) - { - child.setMailingLists( parent.getMailingLists() ); - } - - // Build - assembleBuildInheritance( child, parent ); - - assembleDependencyInheritance( child, parent ); - - child.setRepositories( ModelUtils.mergeRepositoryLists( child.getRepositories(), parent.getRepositories() ) ); -// child.setPluginRepositories( -// ModelUtils.mergeRepositoryLists( child.getPluginRepositories(), parent.getPluginRepositories() ) ); - - assembleReportingInheritance( child, parent ); - - assembleDependencyManagementInheritance( child, parent ); - - Properties props = new Properties(); - props.putAll( parent.getProperties() ); - props.putAll( child.getProperties() ); - - child.setProperties( props ); - } - - private void assembleDependencyManagementInheritance( Model child, Model parent ) - { - DependencyManagement parentDepMgmt = parent.getDependencyManagement(); - - DependencyManagement childDepMgmt = child.getDependencyManagement(); - - if ( parentDepMgmt != null ) - { - if ( childDepMgmt == null ) - { - child.setDependencyManagement( parentDepMgmt ); - } - else - { - List childDeps = childDepMgmt.getDependencies(); - - Map mappedChildDeps = new TreeMap<>(); - for ( Dependency dep : childDeps ) - { - mappedChildDeps.put( dep.getManagementKey(), dep ); - } - - for ( Dependency dep : parentDepMgmt.getDependencies() ) - { - if ( !mappedChildDeps.containsKey( dep.getManagementKey() ) ) - { - childDepMgmt.addDependency( dep ); - } - } - } - } - } - - private void assembleReportingInheritance( Model child, Model parent ) - { - // Reports :: aggregate - Reporting childReporting = child.getReporting(); - Reporting parentReporting = parent.getReporting(); - - if ( parentReporting != null ) - { - if ( childReporting == null ) - { - childReporting = new Reporting(); - child.setReporting( childReporting ); - } - - childReporting.setExcludeDefaults( parentReporting.isExcludeDefaults() ); - - if ( StringUtils.isEmpty( childReporting.getOutputDirectory() ) ) - { - childReporting.setOutputDirectory( parentReporting.getOutputDirectory() ); - } - - mergeReportPluginLists( childReporting, parentReporting, true ); - } - } - - private static void mergeReportPluginLists( Reporting child, Reporting parent, boolean handleAsInheritance ) - { - if ( ( child == null ) || ( parent == null ) ) - { - // nothing to do. - return; - } - - List parentPlugins = parent.getPlugins(); - - if ( ( parentPlugins != null ) && !parentPlugins.isEmpty() ) - { - Map assembledPlugins = new TreeMap<>(); - - Map childPlugins = child.getReportPluginsAsMap(); - - for ( ReportPlugin parentPlugin : parentPlugins ) - { - String parentInherited = parentPlugin.getInherited(); - - if ( !handleAsInheritance || ( parentInherited == null ) || Boolean.parseBoolean( parentInherited ) ) - { - - ReportPlugin assembledPlugin = parentPlugin; - - ReportPlugin childPlugin = childPlugins.get( parentPlugin.getKey() ); - - if ( childPlugin != null ) - { - assembledPlugin = childPlugin; - - mergeReportPluginDefinitions( childPlugin, parentPlugin, handleAsInheritance ); - } - - if ( handleAsInheritance && ( parentInherited == null ) ) - { - assembledPlugin.unsetInheritanceApplied(); - } - - assembledPlugins.put( assembledPlugin.getKey(), assembledPlugin ); - } - } - - for ( ReportPlugin childPlugin : childPlugins.values() ) - { - if ( !assembledPlugins.containsKey( childPlugin.getKey() ) ) - { - assembledPlugins.put( childPlugin.getKey(), childPlugin ); - } - } - - child.setPlugins( new ArrayList<>( assembledPlugins.values() ) ); - - child.flushReportPluginMap(); - } - } - - private static void mergeReportSetDefinitions( ReportSet child, ReportSet parent ) - { - List parentReports = parent.getReports(); - List childReports = child.getReports(); - - List reports = new ArrayList<>(); - - if ( ( childReports != null ) && !childReports.isEmpty() ) - { - reports.addAll( childReports ); - } - - if ( parentReports != null ) - { - for ( String report : parentReports ) - { - if ( !reports.contains( report ) ) - { - reports.add( report ); - } - } - } - - child.setReports( reports ); - - Xpp3Dom childConfiguration = (Xpp3Dom) child.getConfiguration(); - Xpp3Dom parentConfiguration = (Xpp3Dom) parent.getConfiguration(); - - childConfiguration = Xpp3Dom.mergeXpp3Dom( childConfiguration, parentConfiguration ); - - child.setConfiguration( childConfiguration ); - } - - - public static void mergeReportPluginDefinitions( ReportPlugin child, ReportPlugin parent, - boolean handleAsInheritance ) - { - if ( ( child == null ) || ( parent == null ) ) - { - // nothing to do. - return; - } - - if ( ( child.getVersion() == null ) && ( parent.getVersion() != null ) ) - { - child.setVersion( parent.getVersion() ); - } - - // from here to the end of the method is dealing with merging of the section. - String parentInherited = parent.getInherited(); - - boolean parentIsInherited = ( parentInherited == null ) || Boolean.parseBoolean( parentInherited ); - - List parentReportSets = parent.getReportSets(); - - if ( ( parentReportSets != null ) && !parentReportSets.isEmpty() ) - { - Map assembledReportSets = new TreeMap<>(); - - Map childReportSets = child.getReportSetsAsMap(); - - for ( Object parentReportSet1 : parentReportSets ) - { - ReportSet parentReportSet = (ReportSet) parentReportSet1; - - if ( !handleAsInheritance || parentIsInherited ) - { - ReportSet assembledReportSet = parentReportSet; - - ReportSet childReportSet = childReportSets.get( parentReportSet.getId() ); - - if ( childReportSet != null ) - { - mergeReportSetDefinitions( childReportSet, parentReportSet ); - - assembledReportSet = childReportSet; - } - else if ( handleAsInheritance && ( parentInherited == null ) ) - { - parentReportSet.unsetInheritanceApplied(); - } - - assembledReportSets.put( assembledReportSet.getId(), assembledReportSet ); - } - } - - for ( Map.Entry entry : childReportSets.entrySet() ) - { - String id = entry.getKey(); - - if ( !assembledReportSets.containsKey( id ) ) - { - assembledReportSets.put( id, entry.getValue() ); - } - } - - child.setReportSets( new ArrayList<>( assembledReportSets.values() ) ); - - child.flushReportSetMap(); - } - - } - - private void assembleDependencyInheritance( Model child, Model parent ) - { - Map depsMap = new LinkedHashMap<>(); - - List deps = parent.getDependencies(); - - if ( deps != null ) - { - for ( Dependency dependency : deps ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - deps = child.getDependencies(); - - if ( deps != null ) - { - for ( Dependency dependency : deps ) - { - depsMap.put( dependency.getManagementKey(), dependency ); - } - } - - child.setDependencies( new ArrayList<>( depsMap.values() ) ); - } - - private void assembleBuildInheritance( Model child, Model parent ) - { - Build childBuild = child.getBuild(); - Build parentBuild = parent.getBuild(); - - if ( parentBuild != null ) - { - if ( childBuild == null ) - { - childBuild = new Build(); - child.setBuild( childBuild ); - } - - assembleBuildInheritance( childBuild, parentBuild, true ); - } - } - - private void assembleDistributionInheritance( Model child, Model parent, String childPathAdjustment, - boolean appendPaths ) - { - if ( parent.getDistributionManagement() != null ) - { - DistributionManagement parentDistMgmt = parent.getDistributionManagement(); - - DistributionManagement childDistMgmt = child.getDistributionManagement(); - - if ( childDistMgmt == null ) - { - childDistMgmt = new DistributionManagement(); - - child.setDistributionManagement( childDistMgmt ); - } - - if ( childDistMgmt.getSite() == null ) - { - if ( parentDistMgmt.getSite() != null ) - { - Site site = new Site(); - - childDistMgmt.setSite( site ); - - site.setId( parentDistMgmt.getSite().getId() ); - - site.setName( parentDistMgmt.getSite().getName() ); - - site.setUrl( parentDistMgmt.getSite().getUrl() ); - - if ( site.getUrl() != null ) - { - site.setUrl( - appendPath( site.getUrl(), child.getArtifactId(), childPathAdjustment, appendPaths ) ); - } - } - } - - if ( childDistMgmt.getRepository() == null ) - { - if ( parentDistMgmt.getRepository() != null ) - { - DeploymentRepository repository = copyDistributionRepository( parentDistMgmt.getRepository() ); - childDistMgmt.setRepository( repository ); - } - } - - if ( childDistMgmt.getSnapshotRepository() == null ) - { - if ( parentDistMgmt.getSnapshotRepository() != null ) - { - DeploymentRepository repository = - copyDistributionRepository( parentDistMgmt.getSnapshotRepository() ); - childDistMgmt.setSnapshotRepository( repository ); - } - } - - if ( StringUtils.isEmpty( childDistMgmt.getDownloadUrl() ) ) - { - childDistMgmt.setDownloadUrl( parentDistMgmt.getDownloadUrl() ); - } - - // NOTE: We SHOULD NOT be inheriting status, since this is an assessment of the POM quality. - // NOTE: We SHOULD NOT be inheriting relocation, since this relates to a single POM - } - } - - private static DeploymentRepository copyDistributionRepository( DeploymentRepository parentRepository ) - { - DeploymentRepository repository = new DeploymentRepository(); - - repository.setId( parentRepository.getId() ); - - repository.setName( parentRepository.getName() ); - - repository.setUrl( parentRepository.getUrl() ); - - repository.setLayout( parentRepository.getLayout() ); - - repository.setUniqueVersion( parentRepository.isUniqueVersion() ); - - return repository; - } - - // TODO This should eventually be migrated to DefaultPathTranslator. - protected String appendPath( String parentPath, String childPath, String pathAdjustment, boolean appendPaths ) - { - String uncleanPath = parentPath; - - if ( appendPaths ) - { - if ( pathAdjustment != null ) - { - uncleanPath += "/" + pathAdjustment; - } - - if ( childPath != null ) - { - uncleanPath += "/" + childPath; - } - } - - String cleanedPath = ""; - - int protocolIdx = uncleanPath.indexOf( "://" ); - - if ( protocolIdx > -1 ) - { - cleanedPath = uncleanPath.substring( 0, protocolIdx + 3 ); - uncleanPath = uncleanPath.substring( protocolIdx + 3 ); - } - - if ( uncleanPath.startsWith( "/" ) ) - { - cleanedPath += "/"; - } - - return cleanedPath + resolvePath( uncleanPath ); + throw new UnsupportedOperationException(); } - // TODO Move this to plexus-utils' PathTool. - private static String resolvePath( String uncleanPath ) + @Override + public void assembleBuildInheritance( Build childBuild, Build parentBuild, boolean handleAsInheritance ) { - LinkedList pathElements = new LinkedList<>(); - - StringTokenizer tokenizer = new StringTokenizer( uncleanPath, "/" ); - - while ( tokenizer.hasMoreTokens() ) - { - String token = tokenizer.nextToken(); - - switch ( token ) - { - case "": - // Empty path entry ("...//.."), remove. - break; - case "..": - if ( pathElements.isEmpty() ) - { - // FIXME: somehow report to the user - // that there are too many '..' elements. - // For now, ignore the extra '..'. - } - else - { - pathElements.removeLast(); - } - break; - default: - pathElements.addLast( token ); - break; - } - } - - StringBuilder cleanedPath = new StringBuilder(); - - while ( !pathElements.isEmpty() ) - { - cleanedPath.append( pathElements.removeFirst() ); - if ( !pathElements.isEmpty() ) - { - cleanedPath.append( '/' ); - } - } - - return cleanedPath.toString(); + throw new UnsupportedOperationException(); } - private static void mergeExtensionLists( Build childBuild, Build parentBuild ) + @Override + public void copyModel( Model dest, Model source ) { - for ( Extension e : parentBuild.getExtensions() ) - { - if ( !childBuild.getExtensions().contains( e ) ) - { - childBuild.addExtension( e ); - } - } + throw new UnsupportedOperationException(); } -} +} \ No newline at end of file diff --git a/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java b/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java index 6406b5844dbd..4882387690d3 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java +++ b/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java @@ -49,7 +49,7 @@ public ModelValidationResult validate( Model model ) SimpleModelProblemCollector problems = new SimpleModelProblemCollector( result ); - modelValidator.validateEffectiveModel( model, request, problems ); + modelValidator.validateEffectiveModel( model.getDelegate(), request, problems ); return result; } diff --git a/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java b/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java index 8c95385e50cc..8829e34f17a9 100644 --- a/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java +++ b/maven-compat/src/main/java/org/apache/maven/repository/legacy/LegacyRepositorySystem.java @@ -84,7 +84,7 @@ */ @Component( role = RepositorySystem.class, hint = "default" ) public class LegacyRepositorySystem - implements RepositorySystem + implements RepositorySystem { @Requirement @@ -146,13 +146,13 @@ public Artifact createDependencyArtifact( Dependency d ) { // MNG-5368: Log a message instead of returning 'null' silently. this.logger.error( String.format( "Invalid version specification '%s' creating dependency artifact '%s'.", - d.getVersion(), d ), e ); + d.getVersion(), d ), e ); return null; } Artifact artifact = - artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange, d.getType(), - d.getClassifier(), d.getScope(), d.isOptional() ); + artifactFactory.createDependencyArtifact( d.getGroupId(), d.getArtifactId(), versionRange, d.getType(), + d.getClassifier(), d.getScope(), d.isOptional() ); if ( Artifact.SCOPE_SYSTEM.equals( d.getScope() ) && d.getSystemPath() != null ) { @@ -185,8 +185,8 @@ public Artifact createExtensionArtifact( String groupId, String artifactId, Stri { // MNG-5368: Log a message instead of returning 'null' silently. this.logger.error( String.format( - "Invalid version specification '%s' creating extension artifact '%s:%s:%s'.", - version, groupId, artifactId, version ), e ); + "Invalid version specification '%s' creating extension artifact '%s:%s:%s'.", + version, groupId, artifactId, version ), e ); return null; } @@ -216,8 +216,8 @@ public Artifact createPluginArtifact( Plugin plugin ) { // MNG-5368: Log a message instead of returning 'null' silently. this.logger.error( String.format( - "Invalid version specification '%s' creating plugin artifact '%s'.", - version, plugin ), e ); + "Invalid version specification '%s' creating plugin artifact '%s'.", + version, plugin ), e ); return null; } @@ -251,41 +251,41 @@ public ArtifactRepositoryPolicy buildArtifactRepositoryPolicy( RepositoryPolicy } public ArtifactRepository createDefaultLocalRepository() - throws InvalidRepositoryException + throws InvalidRepositoryException { return createLocalRepository( RepositorySystem.defaultUserLocalRepository ); } public ArtifactRepository createLocalRepository( File localRepository ) - throws InvalidRepositoryException + throws InvalidRepositoryException { return createRepository( "file://" + localRepository.toURI().getRawPath(), - RepositorySystem.DEFAULT_LOCAL_REPO_ID, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, - ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); + RepositorySystem.DEFAULT_LOCAL_REPO_ID, true, + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, + ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); } public ArtifactRepository createDefaultRemoteRepository() - throws InvalidRepositoryException + throws InvalidRepositoryException { return createRepository( RepositorySystem.DEFAULT_REMOTE_REPO_URL, RepositorySystem.DEFAULT_REMOTE_REPO_ID, - true, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, false, - ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, - ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN ); + true, ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, false, + ArtifactRepositoryPolicy.UPDATE_POLICY_DAILY, + ArtifactRepositoryPolicy.CHECKSUM_POLICY_WARN ); } public ArtifactRepository createLocalRepository( String url, String repositoryId ) - throws IOException + throws IOException { return createRepository( canonicalFileUrl( url ), repositoryId, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, - ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, - ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, true, + ArtifactRepositoryPolicy.UPDATE_POLICY_ALWAYS, + ArtifactRepositoryPolicy.CHECKSUM_POLICY_IGNORE ); } private String canonicalFileUrl( String url ) - throws IOException + throws IOException { if ( !url.startsWith( "file:" ) ) { @@ -322,12 +322,12 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) try { LocalArtifactRepository ideWorkspace = - plexus.lookup( LocalArtifactRepository.class, LocalArtifactRepository.IDE_WORKSPACE ); + plexus.lookup( LocalArtifactRepository.class, LocalArtifactRepository.IDE_WORKSPACE ); if ( request.getLocalRepository() instanceof DelegatingLocalArtifactRepository ) { DelegatingLocalArtifactRepository delegatingLocalRepository = - (DelegatingLocalArtifactRepository) request.getLocalRepository(); + (DelegatingLocalArtifactRepository) request.getLocalRepository(); LocalArtifactRepository orig = delegatingLocalRepository.getIdeWorkspace(); @@ -346,7 +346,7 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) { ArtifactRepository localRepository = request.getLocalRepository(); DelegatingLocalArtifactRepository delegatingLocalRepository = - new DelegatingLocalArtifactRepository( localRepository ); + new DelegatingLocalArtifactRepository( localRepository ); delegatingLocalRepository.setIdeWorkspace( ideWorkspace ); request.setLocalRepository( delegatingLocalRepository ); try @@ -367,21 +367,21 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) return artifactResolver.resolve( request ); } -// public void addProxy( String protocol, String host, int port, String username, String password, -// String nonProxyHosts ) -// { -// ProxyInfo proxyInfo = new ProxyInfo(); -// proxyInfo.setHost( host ); -// proxyInfo.setType( protocol ); -// proxyInfo.setPort( port ); -// proxyInfo.setNonProxyHosts( nonProxyHosts ); -// proxyInfo.setUserName( username ); -// proxyInfo.setPassword( password ); -// -// proxies.put( protocol, proxyInfo ); -// -// wagonManager.addProxy( protocol, host, port, username, password, nonProxyHosts ); -// } + // public void addProxy( String protocol, String host, int port, String username, String password, + // String nonProxyHosts ) + // { + // ProxyInfo proxyInfo = new ProxyInfo(); + // proxyInfo.setHost( host ); + // proxyInfo.setType( protocol ); + // proxyInfo.setPort( port ); + // proxyInfo.setNonProxyHosts( nonProxyHosts ); + // proxyInfo.setUserName( username ); + // proxyInfo.setPassword( password ); + // + // proxies.put( protocol, proxyInfo ); + // + // wagonManager.addProxy( protocol, host, port, username, password, nonProxyHosts ); + // } public List getEffectiveRepositories( List repositories ) { @@ -408,7 +408,7 @@ public List getEffectiveRepositories( List mirroredRepos = new ArrayList<>(); List releasePolicies = - new ArrayList<>( aliasedRepos.size() ); + new ArrayList<>( aliasedRepos.size() ); for ( ArtifactRepository aliasedRepo : aliasedRepos ) { @@ -419,7 +419,7 @@ public List getEffectiveRepositories( List snapshotPolicies = - new ArrayList<>( aliasedRepos.size() ); + new ArrayList<>( aliasedRepos.size() ); for ( ArtifactRepository aliasedRepo : aliasedRepos ) { @@ -431,8 +431,8 @@ public List getEffectiveRepositories( List repositories, List repositories, List - * Given: - *

- *
-     *   parent: X -> A -> B -> D -> E
-     *   child: Y -> A -> C -> D -> F
-     * 
- *

- * Result: - *

- *
-     *   X -> Y -> A -> B -> C -> D -> E -> F
-     * 
- */ - @Test - public void testShouldPreserveChildOrderingOfPluginsAfterParentMerge() - { - PluginContainer parent = new PluginContainer(); - - parent.addPlugin( createPlugin( "group", "artifact", "1.0", Collections.EMPTY_MAP ) ); - parent.addPlugin( createPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key", "value" ) ) ); - - PluginContainer child = new PluginContainer(); - - child.addPlugin( createPlugin( "group3", "artifact3", "1.0", Collections.EMPTY_MAP ) ); - child.addPlugin( createPlugin( "group2", "artifact2", "1.0", Collections.singletonMap( "key2", "value2" ) ) ); - - ModelUtils.mergePluginLists( child, parent, true ); - - List results = child.getPlugins(); - - assertEquals( 3, results.size() ); - - Plugin result1 = (Plugin) results.get( 0 ); - - assertEquals( "group", result1.getGroupId() ); - assertEquals( "artifact", result1.getArtifactId() ); - - Plugin result2 = (Plugin) results.get( 1 ); - - assertEquals( "group3", result2.getGroupId() ); - assertEquals( "artifact3", result2.getArtifactId() ); - - Plugin result3 = (Plugin) results.get( 2 ); - - assertEquals( "group2", result3.getGroupId() ); - assertEquals( "artifact2", result3.getArtifactId() ); - - Xpp3Dom result3Config = (Xpp3Dom) result3.getConfiguration(); - - assertNotNull( result3Config ); - - assertEquals( "value", result3Config.getChild( "key" ).getValue() ); - assertEquals( "value2", result3Config.getChild( "key2" ).getValue() ); - } - - private Plugin createPlugin( String groupId, String artifactId, String version, Map configuration ) - { - Plugin plugin = new Plugin(); - plugin.setGroupId( groupId ); - plugin.setArtifactId( artifactId ); - plugin.setVersion( version ); - - Xpp3Dom config = new Xpp3Dom( "configuration" ); - - if( configuration != null ) - { - for ( Object o : configuration.entrySet() ) - { - Map.Entry entry = (Map.Entry) o; - - Xpp3Dom param = new Xpp3Dom( String.valueOf( entry.getKey() ) ); - param.setValue( String.valueOf( entry.getValue() ) ); - - config.addChild( param ); - } - } - - plugin.setConfiguration( config ); - - return plugin; - } - - @Test - public void testShouldInheritOnePluginWithExecution() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - ModelUtils.mergePluginDefinitions( child, parent, false ); - - assertEquals( 1, child.getExecutions().size() ); - } - - @Test - public void testShouldMergeInheritedPluginHavingExecutionWithLocalPlugin() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - PluginExecution childExecution = new PluginExecution(); - childExecution.setId( "testExecution2" ); - - child.addExecution( childExecution ); - - ModelUtils.mergePluginDefinitions( child, parent, false ); - - assertEquals( 2, child.getExecutions().size() ); - } - - @Test - public void testShouldMergeOnePluginWithInheritExecutionWithoutDuplicatingPluginInList() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Build parentContainer = new Build(); - parentContainer.addPlugin( parent ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - Build childContainer = new Build(); - childContainer.addPlugin( child ); - - ModelUtils.mergePluginLists( childContainer, parentContainer, true ); - - List plugins = childContainer.getPlugins(); - - assertEquals( 1, plugins.size() ); - - Plugin plugin = (Plugin) plugins.get( 0 ); - - assertEquals( 1, plugin.getExecutions().size() ); - } - - @Test - public void testShouldMergePluginWithDifferentExecutionFromParentWithoutDuplicatingPluginInList() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Build parentContainer = new Build(); - parentContainer.addPlugin( parent ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - PluginExecution childExecution = new PluginExecution(); - childExecution.setId( "testExecution2" ); - - child.addExecution( childExecution ); - - - Build childContainer = new Build(); - childContainer.addPlugin( child ); - - ModelUtils.mergePluginLists( childContainer, parentContainer, true ); - - List plugins = childContainer.getPlugins(); - - assertEquals( 1, plugins.size() ); - - Plugin plugin = (Plugin) plugins.get( 0 ); - - assertEquals( 2, plugin.getExecutions().size() ); - } - - @Test - public void testShouldNOTMergeInheritedPluginHavingInheritEqualFalse() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - parent.setInherited( "false" ); - - PluginExecution parentExecution = new PluginExecution(); - parentExecution.setId( "testExecution" ); - - parent.addExecution( parentExecution ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - ModelUtils.mergePluginDefinitions( child, parent, true ); - - assertEquals( 0, child.getExecutions().size() ); - } - - /** - * Verifies MNG-1499: The order of the merged list should be the plugins specified by the parent followed by the - * child list. - */ - @Test - public void testShouldKeepOriginalPluginOrdering() - { - Plugin parentPlugin1 = new Plugin(); - parentPlugin1.setArtifactId( "testArtifact" ); - parentPlugin1.setGroupId( "zzz" ); // This will put this plugin last in the sorted map - parentPlugin1.setVersion( "1.0" ); - - PluginExecution parentExecution1 = new PluginExecution(); - parentExecution1.setId( "testExecution" ); - - parentPlugin1.addExecution( parentExecution1 ); - - Plugin parentPlugin2 = new Plugin(); - parentPlugin2.setArtifactId( "testArtifact" ); - parentPlugin2.setGroupId( "yyy" ); - parentPlugin2.setVersion( "1.0" ); - - PluginExecution parentExecution2 = new PluginExecution(); - parentExecution2.setId( "testExecution" ); - - parentPlugin2.addExecution( parentExecution2 ); - - PluginContainer parentContainer = new PluginContainer(); - parentContainer.addPlugin(parentPlugin1); - parentContainer.addPlugin(parentPlugin2); - - - Plugin childPlugin1 = new Plugin(); - childPlugin1.setArtifactId( "testArtifact" ); - childPlugin1.setGroupId( "bbb" ); - childPlugin1.setVersion( "1.0" ); - - PluginExecution childExecution1 = new PluginExecution(); - childExecution1.setId( "testExecution" ); - - childPlugin1.addExecution( childExecution1 ); - - Plugin childPlugin2 = new Plugin(); - childPlugin2.setArtifactId( "testArtifact" ); - childPlugin2.setGroupId( "aaa" ); - childPlugin2.setVersion( "1.0" ); - - PluginExecution childExecution2 = new PluginExecution(); - childExecution2.setId( "testExecution" ); - - childPlugin2.addExecution( childExecution2 ); - - PluginContainer childContainer = new PluginContainer(); - childContainer.addPlugin(childPlugin1); - childContainer.addPlugin(childPlugin2); - - - ModelUtils.mergePluginLists(childContainer, parentContainer, true); - - assertEquals( 4, childContainer.getPlugins().size() ); - assertSame(parentPlugin1, childContainer.getPlugins().get(0)); - assertSame(parentPlugin2, childContainer.getPlugins().get(1)); - assertSame(childPlugin1, childContainer.getPlugins().get(2)); - assertSame(childPlugin2, childContainer.getPlugins().get(3)); - } - - /** - * Verifies MNG-1499: The ordering of plugin executions should also be in the specified order. - */ - @Test - public void testShouldKeepOriginalPluginExecutionOrdering() - { - Plugin parent = new Plugin(); - parent.setArtifactId( "testArtifact" ); - parent.setGroupId( "testGroup" ); - parent.setVersion( "1.0" ); - - PluginExecution parentExecution1 = new PluginExecution(); - parentExecution1.setId( "zzz" ); // Will show up last in the sorted map - PluginExecution parentExecution2 = new PluginExecution(); - parentExecution2.setId( "yyy" ); // Will show up last in the sorted map - - parent.addExecution( parentExecution1 ); - parent.addExecution( parentExecution2 ); - - // this block verifies MNG-1703 - Dependency dep = new Dependency(); - dep.setGroupId( "depGroupId" ); - dep.setArtifactId( "depArtifactId" ); - dep.setVersion( "depVersion" ); - parent.setDependencies( Collections.singletonList( dep ) ); - - Plugin child = new Plugin(); - child.setArtifactId( "testArtifact" ); - child.setGroupId( "testGroup" ); - child.setVersion( "1.0" ); - - PluginExecution childExecution1 = new PluginExecution(); - childExecution1.setId( "bbb" ); - PluginExecution childExecution2 = new PluginExecution(); - childExecution2.setId( "aaa" ); - - child.addExecution( childExecution1 ); - child.addExecution( childExecution2 ); - - ModelUtils.mergePluginDefinitions( child, parent, false ); - - assertEquals( 4, child.getExecutions().size() ); - assertSame(parentExecution1, child.getExecutions().get(0)); - assertSame(parentExecution2, child.getExecutions().get(1)); - assertSame(childExecution1, child.getExecutions().get(2)); - assertSame(childExecution2, child.getExecutions().get(3)); - - // this block prevents MNG-1703 - assertEquals( 1, child.getDependencies().size() ); - Dependency dep2 = child.getDependencies().get( 0 ); - assertEquals( dep.getManagementKey(), dep2.getManagementKey() ); - } - - @Test - public void testShouldOverwritePluginConfigurationSubItemsByDefault() - throws XmlPullParserException, IOException - { - String parentConfigStr = "onetwo"; - Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) ); - - Plugin parentPlugin = createPlugin( "group", "artifact", "1", null ); - parentPlugin.setConfiguration( parentConfig ); - - String childConfigStr = "three"; - Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) ); - - Plugin childPlugin = createPlugin( "group", "artifact", "1", null ); - childPlugin.setConfiguration( childConfig ); - - ModelUtils.mergePluginDefinitions( childPlugin, parentPlugin, true ); - - Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration(); - Xpp3Dom items = result.getChild( "items" ); - - assertEquals( 1, items.getChildCount() ); - - Xpp3Dom item = items.getChild( 0 ); - assertEquals( "three", item.getValue() ); - } - - @Test - public void testShouldMergePluginConfigurationSubItemsWithMergeAttributeSet() - throws XmlPullParserException, IOException - { - String parentConfigStr = "onetwo"; - Xpp3Dom parentConfig = Xpp3DomBuilder.build( new StringReader( parentConfigStr ) ); - - Plugin parentPlugin = createPlugin( "group", "artifact", "1", null ); - parentPlugin.setConfiguration( parentConfig ); - - String childConfigStr = "three"; - Xpp3Dom childConfig = Xpp3DomBuilder.build( new StringReader( childConfigStr ) ); - - Plugin childPlugin = createPlugin( "group", "artifact", "1", null ); - childPlugin.setConfiguration( childConfig ); - - ModelUtils.mergePluginDefinitions( childPlugin, parentPlugin, true ); - - Xpp3Dom result = (Xpp3Dom) childPlugin.getConfiguration(); - Xpp3Dom items = result.getChild( "items" ); - - assertEquals( 3, items.getChildCount() ); - - Xpp3Dom[] item = items.getChildren(); - - List actual = Arrays.asList( item[0].getValue(), item[1].getValue(), item[2].getValue() ); - List expected = Arrays.asList( "one", "two", "three" ); - Collections.sort( actual ); - Collections.sort( expected ); - assertEquals( expected, actual ); - } - - @Test - public void testShouldNotMergePluginExecutionWhenExecInheritedIsFalseAndTreatAsInheritanceIsTrue() - { - String gid = "group"; - String aid = "artifact"; - String ver = "1"; - - PluginContainer parent = new PluginContainer(); - Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - - pParent.setInherited( Boolean.toString( true ) ); - - PluginExecution eParent = new PluginExecution(); - - String testId = "test"; - - eParent.setId( testId ); - eParent.addGoal( "run" ); - eParent.setPhase( "initialize" ); - eParent.setInherited( Boolean.toString( false ) ); - - pParent.addExecution( eParent ); - parent.addPlugin( pParent ); - - PluginContainer child = new PluginContainer(); - Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - PluginExecution eChild = new PluginExecution(); - - eChild.setId( "child-specified" ); - eChild.addGoal( "child" ); - eChild.setPhase( "compile" ); - - pChild.addExecution( eChild ); - child.addPlugin( pChild ); - - ModelUtils.mergePluginDefinitions( pChild, pParent, true ); - - Map executionMap = pChild.getExecutionsAsMap(); - assertNull( executionMap.get( testId ), "test execution should not be inherited from parent." ); - } - - @Test - public void testShouldNotMergePluginExecutionWhenPluginInheritedIsFalseAndTreatAsInheritanceIsTrue() - { - String gid = "group"; - String aid = "artifact"; - String ver = "1"; - - PluginContainer parent = new PluginContainer(); - Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - - pParent.setInherited( Boolean.toString( false ) ); - - PluginExecution eParent = new PluginExecution(); - - String testId = "test"; - - eParent.setId( testId ); - eParent.addGoal( "run" ); - eParent.setPhase( "initialize" ); - eParent.setInherited( Boolean.toString( true ) ); - - pParent.addExecution( eParent ); - parent.addPlugin( pParent ); - - PluginContainer child = new PluginContainer(); - Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - PluginExecution eChild = new PluginExecution(); - - eChild.setId( "child-specified" ); - eChild.addGoal( "child" ); - eChild.setPhase( "compile" ); - - pChild.addExecution( eChild ); - child.addPlugin( pChild ); - - ModelUtils.mergePluginDefinitions( pChild, pParent, true ); - - Map executionMap = pChild.getExecutionsAsMap(); - assertNull( executionMap.get( testId ), "test execution should not be inherited from parent." ); - } - - @Test - public void testShouldMergePluginExecutionWhenExecInheritedIsTrueAndTreatAsInheritanceIsTrue() - { - String gid = "group"; - String aid = "artifact"; - String ver = "1"; - - PluginContainer parent = new PluginContainer(); - Plugin pParent = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - - pParent.setInherited( Boolean.toString( true ) ); - - PluginExecution eParent = new PluginExecution(); - - String testId = "test"; - - eParent.setId( testId ); - eParent.addGoal( "run" ); - eParent.setPhase( "initialize" ); - eParent.setInherited( Boolean.toString( true ) ); - - pParent.addExecution( eParent ); - parent.addPlugin( pParent ); - - PluginContainer child = new PluginContainer(); - Plugin pChild = createPlugin( gid, aid, ver, Collections.EMPTY_MAP ); - PluginExecution eChild = new PluginExecution(); - - eChild.setId( "child-specified" ); - eChild.addGoal( "child" ); - eChild.setPhase( "compile" ); - - pChild.addExecution( eChild ); - child.addPlugin( pChild ); - - ModelUtils.mergePluginDefinitions( pChild, pParent, true ); - - Map executionMap = pChild.getExecutionsAsMap(); - assertNotNull( executionMap.get( testId ), "test execution should be inherited from parent." ); - } - -} diff --git a/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java b/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java index 50f5f0894192..25adce840283 100644 --- a/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java +++ b/maven-compat/src/test/java/org/apache/maven/project/inheritance/t12/ProjectInheritanceTest.java @@ -21,8 +21,10 @@ import java.io.File; import java.util.Map; +import java.util.stream.Collectors; import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginExecution; import org.apache.maven.project.MavenProject; import org.apache.maven.project.inheritance.AbstractProjectInheritanceTestCase; import org.junit.jupiter.api.Test; diff --git a/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java b/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java index f68a9961fb80..78353beb827f 100644 --- a/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java +++ b/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java @@ -67,7 +67,7 @@ protected List getRemoteRepositories() File repoDir = new File( getBasedir(), "src/test/remote-repo" ).getAbsoluteFile(); RepositoryPolicy policy = new RepositoryPolicy(); - policy.setEnabled( true ); + policy.setEnabled( Boolean.toString( true ) ); policy.setChecksumPolicy( "ignore" ); policy.setUpdatePolicy( "always" ); diff --git a/maven-core/pom.xml b/maven-core/pom.xml index f46fdeb1d998..bb3ef5463cf7 100644 --- a/maven-core/pom.xml +++ b/maven-core/pom.xml @@ -84,6 +84,10 @@ under the License. org.apache.maven maven-resolver-provider
+ + org.apache.maven + maven-api-core + org.apache.maven.resolver maven-resolver-impl diff --git a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java index 56a42b72444e..bbea3aa03600 100644 --- a/maven-core/src/main/java/org/apache/maven/DefaultMaven.java +++ b/maven-core/src/main/java/org/apache/maven/DefaultMaven.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Session; import org.apache.maven.artifact.ArtifactUtils; import org.apache.maven.execution.BuildResumptionAnalyzer; import org.apache.maven.execution.BuildResumptionDataRepository; @@ -32,12 +33,13 @@ import org.apache.maven.execution.ProjectDependencyGraph; import org.apache.maven.graph.GraphBuilder; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; +import org.apache.maven.internal.impl.DefaultSessionFactory; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.lifecycle.internal.ExecutionEventCatapult; import org.apache.maven.lifecycle.internal.LifecycleStarter; -import org.apache.maven.model.Model; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Prerequisites; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblem; import org.apache.maven.model.building.Result; import org.apache.maven.model.superpom.SuperPomProvider; @@ -107,7 +109,10 @@ public class DefaultMaven private final SuperPomProvider superPomProvider; + private final DefaultSessionFactory defaultSessionFactory; + @Inject + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultMaven( ProjectBuilder projectBuilder, LifecycleStarter lifecycleStarter, @@ -119,7 +124,8 @@ public DefaultMaven( @Named( GraphBuilder.HINT ) GraphBuilder graphBuilder, BuildResumptionAnalyzer buildResumptionAnalyzer, BuildResumptionDataRepository buildResumptionDataRepository, - SuperPomProvider superPomProvider ) + SuperPomProvider superPomProvider, + DefaultSessionFactory defaultSessionFactory ) { this.projectBuilder = projectBuilder; this.lifecycleStarter = lifecycleStarter; @@ -132,6 +138,7 @@ public DefaultMaven( this.buildResumptionAnalyzer = buildResumptionAnalyzer; this.buildResumptionDataRepository = buildResumptionDataRepository; this.superPomProvider = superPomProvider; + this.defaultSessionFactory = defaultSessionFactory; } @Override @@ -223,8 +230,10 @@ private MavenExecutionResult doExecute( MavenExecutionRequest request ) DefaultRepositorySystemSession repoSession = (DefaultRepositorySystemSession) newRepositorySession( request ); MavenSession session = new MavenSession( container, repoSession, request, result ); + session.setSession( defaultSessionFactory.getSession( session ) ); sessionScope.seed( MavenSession.class, session ); + sessionScope.seed( Session.class, session.getSession() ); legacySupport.setSession( session ); @@ -557,7 +566,7 @@ private void validatePrerequisitesForNonMavenPluginProjects( List { if ( !"maven-plugin".equals( mavenProject.getPackaging() ) ) { - Prerequisites prerequisites = mavenProject.getPrerequisites(); + Prerequisites prerequisites = mavenProject.getModel().getDelegate().getPrerequisites(); if ( prerequisites != null && prerequisites.getMaven() != null ) { logger.warn( "The project " + mavenProject.getId() + " uses prerequisites" @@ -591,9 +600,7 @@ private Set getAllProfiles( MavenSession session ) } final Stream projectProfiles = projectsIncludingParents.stream() - .map( MavenProject::getModel ) - .map( Model::getProfiles ) - .flatMap( Collection::stream ) + .flatMap( p -> p.getModel().getDelegate().getProfiles().stream() ) .map( Profile::getId ); final Stream settingsProfiles = session.getSettings().getProfiles().stream() .map( org.apache.maven.settings.Profile::getId ); diff --git a/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java b/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java index bb90aff28020..d0d2bf467103 100644 --- a/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java +++ b/maven-core/src/main/java/org/apache/maven/artifact/handler/DefaultArtifactHandler.java @@ -70,6 +70,7 @@ public DefaultArtifactHandler( final String type ) ); } + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultArtifactHandler( final String type, final String extension, final String classifier, diff --git a/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java b/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java index 79563822d05c..0f7689f629ab 100644 --- a/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java +++ b/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java @@ -350,7 +350,7 @@ public static org.apache.maven.model.RepositoryPolicy fromSettingsRepositoryPoli org.apache.maven.model.RepositoryPolicy modelRepositoryPolicy = new org.apache.maven.model.RepositoryPolicy(); if ( settingsRepositoryPolicy != null ) { - modelRepositoryPolicy.setEnabled( settingsRepositoryPolicy.isEnabled() ); + modelRepositoryPolicy.setEnabled( Boolean.toString( settingsRepositoryPolicy.isEnabled() ) ); modelRepositoryPolicy.setUpdatePolicy( settingsRepositoryPolicy.getUpdatePolicy() ); modelRepositoryPolicy.setChecksumPolicy( settingsRepositoryPolicy.getChecksumPolicy() ); } diff --git a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java index 94e9eccd4ab3..6737c81aa3b9 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java +++ b/maven-core/src/main/java/org/apache/maven/execution/DefaultMavenExecutionRequestPopulator.java @@ -283,7 +283,7 @@ public MavenExecutionRequest populateFromSettings( MavenExecutionRequest request for ( org.apache.maven.settings.Profile rawProfile : settings.getProfiles() ) { - request.addProfile( SettingsUtils.convertFromSettingsProfile( rawProfile ) ); + request.addProfile( SettingsUtils.convertFromSettingsProfile( rawProfile.getDelegate() ) ); if ( settings.getActiveProfiles().contains( rawProfile.getId() ) ) { @@ -292,7 +292,8 @@ public MavenExecutionRequest populateFromSettings( MavenExecutionRequest request { try { - request.addRemoteRepository( repositorySystem.buildArtifactRepository( remoteRepository ) ); + request.addRemoteRepository( + MavenRepositorySystem.buildArtifactRepository( remoteRepository ) ); } catch ( InvalidRepositoryException e ) { @@ -305,7 +306,8 @@ public MavenExecutionRequest populateFromSettings( MavenExecutionRequest request { try { - request.addPluginArtifactRepository( repositorySystem.buildArtifactRepository( pluginRepo ) ); + request.addPluginArtifactRepository( + MavenRepositorySystem.buildArtifactRepository( pluginRepo ) ); } catch ( InvalidRepositoryException e ) { diff --git a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java index c2f0c89e862e..e7b0d368897d 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java +++ b/maven-core/src/main/java/org/apache/maven/execution/MavenSession.java @@ -27,14 +27,20 @@ import java.util.Properties; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.ConcurrentMap; +import java.util.stream.Collectors; +import org.apache.maven.api.Session; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.artifact.repository.RepositoryCache; import org.apache.maven.monitor.event.EventDispatcher; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Server; import org.apache.maven.settings.Settings; +import org.apache.maven.settings.SettingsUtils; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.eclipse.aether.RepositorySystemSession; @@ -297,6 +303,8 @@ public void setAllProjects( List allProjects ) private final Settings settings; + private Session session; + @Deprecated /** @deprecated This appears not to be used anywhere within Maven itself. */ public Map getProjectMap() @@ -311,7 +319,7 @@ public MavenSession( PlexusContainer container, RepositorySystemSession reposito this.container = container; this.request = request; this.result = result; - this.settings = new SettingsAdapter( request ); + this.settings = adaptSettings( request ); this.repositorySession = repositorySession; } @@ -357,10 +365,33 @@ public MavenSession( PlexusContainer container, MavenExecutionRequest request, M this.container = container; this.request = request; this.result = result; - this.settings = new SettingsAdapter( request ); + this.settings = adaptSettings( request ); setProjects( projects ); } + /** + * Adapt a {@link MavenExecutionRequest} to a {@link Settings} object for use in the Maven core. + * We want to make sure that what is ask for in the execution request overrides what is in the settings. + * The CLI feeds into an execution request so if a particular value is present in the execution request + * then we will take that over the value coming from the user settings. + */ + private static Settings adaptSettings( MavenExecutionRequest request ) + { + File localRepo = request.getLocalRepositoryPath(); + return new Settings( org.apache.maven.api.settings.Settings.newBuilder() + .localRepository( localRepo != null ? localRepo.getAbsolutePath() : null ) + .interactiveMode( request.isInteractiveMode() ) + .offline( request.isOffline() ) + .proxies( request.getProxies().stream().map( Proxy::getDelegate ).collect( Collectors.toList() ) ) + .servers( request.getServers().stream().map( Server::getDelegate ).collect( Collectors.toList() ) ) + .mirrors( request.getMirrors().stream().map( Mirror::getDelegate ).collect( Collectors.toList() ) ) + .profiles( request.getProfiles().stream() + .map( SettingsUtils::convertToSettingsProfile ).collect( Collectors.toList() ) ) + .activeProfiles( request.getActiveProfiles() ) + .pluginGroups( request.getPluginGroups() ) + .build() ); + } + @Deprecated public List getSortedProjects() { @@ -439,5 +470,14 @@ public Map lookupMap( String role ) return container.lookupMap( role ); } + public Session getSession() + { + return session; + } + + public void setSession( Session session ) + { + this.session = session; + } /*end[MAVEN4]*/ } diff --git a/maven-core/src/main/java/org/apache/maven/execution/SettingsAdapter.java b/maven-core/src/main/java/org/apache/maven/execution/SettingsAdapter.java deleted file mode 100644 index bf5d3730ec7d..000000000000 --- a/maven-core/src/main/java/org/apache/maven/execution/SettingsAdapter.java +++ /dev/null @@ -1,126 +0,0 @@ -package org.apache.maven.execution; - -/* - * 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. - */ - -import java.io.File; -import java.util.ArrayList; -import java.util.List; - -import org.apache.maven.settings.Mirror; -import org.apache.maven.settings.Profile; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.RuntimeInfo; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.SettingsUtils; - -/** - * Adapt a {@link MavenExecutionRequest} to a {@link Settings} object for use in the Maven core. - * We want to make sure that what is ask for in the execution request overrides what is in the settings. - * The CLI feeds into an execution request so if a particular value is present in the execution request - * then we will take that over the value coming from the user settings. - * - * @author Jason van Zyl - */ -class SettingsAdapter - extends Settings -{ - - private MavenExecutionRequest request; - - private RuntimeInfo runtimeInfo; - - SettingsAdapter( MavenExecutionRequest request ) - { - this.request = request; - - /* - * NOTE: Plugins like maven-release-plugin query the path to the settings.xml to pass it into a forked Maven and - * the CLI will fail when called with a non-existing settings, so be sure to only point at actual files. Having - * a null file should be harmless as this case matches general Maven 2.x behavior... - */ - File userSettings = request.getUserSettingsFile(); - this.runtimeInfo = new RuntimeInfo( ( userSettings != null && userSettings.isFile() ) ? userSettings : null ); - } - - @Override - public String getLocalRepository() - { - if ( request.getLocalRepositoryPath() != null ) - { - return request.getLocalRepositoryPath().getAbsolutePath(); - } - - return null; - } - - @Override - public boolean isInteractiveMode() - { - return request.isInteractiveMode(); - } - - @Override - public boolean isOffline() - { - return request.isOffline(); - } - - @Override - public List getProxies() - { - return request.getProxies(); - } - - @Override - public List getServers() - { - return request.getServers(); - } - - @Override - public List getMirrors() - { - return request.getMirrors(); - } - - @Override - public List getProfiles() - { - List result = new ArrayList<>(); - for ( org.apache.maven.model.Profile profile : request.getProfiles() ) - { - result.add( SettingsUtils.convertToSettingsProfile( profile ) ); - } - return result; - } - - @Override - public List getActiveProfiles() - { - return request.getActiveProfiles(); - } - - @Override - public List getPluginGroups() - { - return request.getPluginGroups(); - } -} diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index d157e7621dd1..aa6781f309a5 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -96,6 +96,7 @@ public class DefaultRepositorySystemSessionFactory private final RuntimeInformation runtimeInformation; + @SuppressWarnings( "checkstyle:ParameterNumber" ) @Inject public DefaultRepositorySystemSessionFactory( ArtifactHandlerManager artifactHandlerManager, @@ -185,8 +186,8 @@ else if ( request.isUpdateSnapshots() ) } DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest(); - decrypt.setProxies( request.getProxies() ); - decrypt.setServers( request.getServers() ); + decrypt.setProxies( Proxy.proxyToApiV4( request.getProxies() ) ); + decrypt.setServers( Server.serverToApiV4( request.getServers() ) ); SettingsDecryptionResult decrypted = settingsDecrypter.decrypt( decrypt ); if ( logger.isDebugEnabled() ) @@ -206,7 +207,7 @@ else if ( request.isUpdateSnapshots() ) session.setMirrorSelector( mirrorSelector ); DefaultProxySelector proxySelector = new DefaultProxySelector(); - for ( Proxy proxy : decrypted.getProxies() ) + for ( org.apache.maven.api.settings.Proxy proxy : decrypted.getProxies() ) { AuthenticationBuilder authBuilder = new AuthenticationBuilder(); authBuilder.addUsername( proxy.getUsername() ).addPassword( proxy.getPassword() ); @@ -217,7 +218,7 @@ else if ( request.isUpdateSnapshots() ) session.setProxySelector( proxySelector ); DefaultAuthenticationSelector authSelector = new DefaultAuthenticationSelector(); - for ( Server server : decrypted.getServers() ) + for ( org.apache.maven.api.settings.Server server : decrypted.getServers() ) { AuthenticationBuilder authBuilder = new AuthenticationBuilder(); authBuilder.addUsername( server.getUsername() ).addPassword( server.getPassword() ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java new file mode 100644 index 000000000000..5ff2ff4194a7 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -0,0 +1,132 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.io.File; +import java.nio.file.Path; +import java.util.Objects; +import java.util.Optional; + +import org.apache.maven.api.Artifact; + +public class DefaultArtifact implements Artifact +{ + private final DefaultSession session; + private final org.eclipse.aether.artifact.Artifact artifact; + + public DefaultArtifact( @Nonnull DefaultSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact ) + { + this.session = Objects.requireNonNull( session ); + this.artifact = Objects.requireNonNull( artifact ); + } + + public org.eclipse.aether.artifact.Artifact getArtifact() + { + return artifact; + } + + @Nonnull + @Override + public String getGroupId() + { + return artifact.getGroupId(); + } + + @Nonnull + @Override + public String getArtifactId() + { + return artifact.getArtifactId(); + } + + @Nonnull + @Override + public String getVersion() + { + return artifact.getVersion(); + } + + @Nonnull + @Override + public String getExtension() + { + return artifact.getExtension(); + } + + @Nonnull + @Override + public String getClassifier() + { + return artifact.getClassifier(); + } + + @Nonnull + @Override + public String getBaseVersion() + { + return artifact.getBaseVersion(); + } + + @Override + public boolean isSnapshot() + { + return artifact.isSnapshot(); + } + + @Nonnull + @Override + public Optional getPath() + { + return Optional.ofNullable( artifact.getFile() ).map( File::toPath ); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + DefaultArtifact that = (DefaultArtifact) o; + return Objects.equals( this.getGroupId(), that.getGroupId() ) + && Objects.equals( this.getArtifactId(), that.getArtifactId() ) + && Objects.equals( this.getVersion(), that.getVersion() ) + && Objects.equals( this.getClassifier(), that.getClassifier() ) + && Objects.equals( this.getExtension(), that.getExtension() ); + } + + @Override + public int hashCode() + { + return Objects.hash( getGroupId(), getArtifactId(), getVersion(), getClassifier(), getExtension() ); + } + + @Override + public String toString() + { + return artifact.toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java new file mode 100644 index 000000000000..39df5f1769bf --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java @@ -0,0 +1,76 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; +import javax.inject.Named; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactDeployerException; +import org.apache.maven.api.services.ArtifactDeployerRequest; +import org.apache.maven.api.services.ArtifactManager; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.deployment.DeployRequest; +import org.eclipse.aether.deployment.DeployResult; +import org.eclipse.aether.deployment.DeploymentException; +import org.eclipse.aether.metadata.Metadata; + +@Named +public class DefaultArtifactDeployer implements ArtifactDeployer +{ + private final RepositorySystem repositorySystem; + + @Inject + DefaultArtifactDeployer( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = Objects.requireNonNull( repositorySystem ); + } + + @Override + public void deploy( ArtifactDeployerRequest request ) throws ArtifactDeployerException, IllegalArgumentException + { + DefaultSession session = ( DefaultSession ) request.getSession(); + try + { + ArtifactManager artifactManager = session.getService( ArtifactManager.class ); + List metadatas = request.getArtifacts().stream() + .map( artifactManager::getAttachedMetadatas ) + .flatMap( Collection::stream ) + .map( session::toMetadata ) + .collect( Collectors.toList() ); + DeployRequest deployRequest = new DeployRequest() + .setRepository( session.toRepository( request.getRepository() ) ) + .setArtifacts( session.toArtifacts( request.getArtifacts() ) ) + .setMetadata( metadatas ); + + DeployResult result = repositorySystem.deploy( session.getSession(), deployRequest ); + } + catch ( DeploymentException e ) + { + throw new ArtifactDeployerException( "Unable to deploy artifacts", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java new file mode 100644 index 000000000000..e4f9b94bc72f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java @@ -0,0 +1,60 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Named; + +import java.security.InvalidParameterException; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactFactoryException; +import org.apache.maven.api.services.ArtifactFactoryRequest; +import org.apache.maven.shared.utils.StringUtils; +import org.eclipse.aether.artifact.ArtifactType; + +@Named +public class DefaultArtifactFactory implements ArtifactFactory +{ + @Override + public Artifact create( ArtifactFactoryRequest request ) throws ArtifactFactoryException, InvalidParameterException + { + DefaultSession session = (DefaultSession) request.getSession(); + ArtifactType type = null; + if ( request.getType() != null ) + { + type = session.getSession().getArtifactTypeRegistry().get( request.getType() ); + } + String classifier = StringUtils.isNotEmpty( request.getClassifier() ) + ? request.getClassifier() + : type != null ? type.getClassifier() : null; + String extension = StringUtils.isNotEmpty( request.getExtension() ) + ? request.getExtension() : type != null ? type.getExtension() : null; + return new DefaultArtifact( + session, + new org.eclipse.aether.artifact.DefaultArtifact( + request.getGroupId(), + request.getArtifactId(), + classifier, + extension, + request.getVersion(), + type ) ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java new file mode 100644 index 000000000000..06a0cc4b4afd --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java @@ -0,0 +1,107 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.stream.Collectors; + +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactInstallerException; +import org.apache.maven.api.services.ArtifactInstallerRequest; +import org.apache.maven.api.services.ArtifactManager; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.installation.InstallRequest; +import org.eclipse.aether.installation.InstallResult; +import org.eclipse.aether.installation.InstallationException; +import org.eclipse.aether.metadata.Metadata; + +public class DefaultArtifactInstaller implements ArtifactInstaller +{ + + private final RepositorySystem repositorySystem; + + DefaultArtifactInstaller( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = Objects.requireNonNull( repositorySystem ); + } + + @Override + public void install( ArtifactInstallerRequest request ) throws ArtifactInstallerException, IllegalArgumentException + { + + /* + // prepare installRequest + InstallRequest request = new InstallRequest(); + + // transform artifacts + for ( org.apache.maven.artifact.Artifact mavenArtifact : mavenArtifacts ) + { + Artifact mainArtifact = RepositoryUtils.toArtifact( mavenArtifact ); + request.addArtifact( mainArtifact ); + + for ( ArtifactMetadata metadata : mavenArtifact.getMetadataList() ) + { + if ( metadata instanceof ProjectArtifactMetadata ) + { + Artifact pomArtifact = new SubArtifact( mainArtifact, "", "pom" ); + pomArtifact = pomArtifact.setFile( ( (ProjectArtifactMetadata) metadata ).getFile() ); + request.addArtifact( pomArtifact ); + } + else if ( // metadata instanceof SnapshotArtifactRepositoryMetadata || + metadata instanceof ArtifactRepositoryMetadata ) + { + // eaten, handled by repo system + } + else if ( metadata instanceof org.apache.maven.shared.transfer.metadata.ArtifactMetadata ) + { + org.apache.maven.shared.transfer.metadata.ArtifactMetadata transferMetadata = + (org.apache.maven.shared.transfer.metadata.ArtifactMetadata) metadata; + + request.addMetadata( new Maven31MetadataBridge( metadata ).setFile( transferMetadata.getFile() ) ); + } + } + } + */ + + DefaultSession session = ( DefaultSession ) request.getSession(); + try + { + ArtifactManager artifactManager = session.getService( ArtifactManager.class ); + List metadatas = request.getArtifacts().stream() + .map( artifactManager::getAttachedMetadatas ) + .flatMap( Collection::stream ) + .map( session::toMetadata ) + .collect( Collectors.toList() ); + InstallRequest installRequest = new InstallRequest() + .setArtifacts( session.toArtifacts( request.getArtifacts() ) ) + .setMetadata( metadatas ); + + InstallResult result = repositorySystem.install( session.getSession(), installRequest ); + } + catch ( InstallationException e ) + { + throw new ArtifactInstallerException( e.getMessage(), e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java new file mode 100644 index 000000000000..5b4ee5d0e5b0 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java @@ -0,0 +1,86 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.Map; +import java.util.Optional; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.regex.Pattern; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.services.ArtifactManager; + +public class DefaultArtifactManager implements ArtifactManager +{ + private static final String SNAPSHOT = "SNAPSHOT"; + private static final Pattern SNAPSHOT_TIMESTAMP = Pattern.compile( "^(.*-)?([0-9]{8}\\.[0-9]{6}-[0-9]+)$" ); + + + private final Map paths = new ConcurrentHashMap<>(); + private final Map> metadatas = new ConcurrentHashMap<>(); + + @Nonnull + @Override + public Optional getPath( @Nonnull Artifact artifact ) + { + Path path = paths.get( artifact ); + return path != null ? Optional.of( path ) : artifact.getPath(); + } + + @Override + public void setPath( @Nonnull Artifact artifact, Path path ) + { + if ( path == null ) + { + paths.remove( artifact ); + } + else + { + paths.put( artifact, path ); + } + } + + @Nonnull + @Override + public Collection getAttachedMetadatas( @Nonnull Artifact artifact ) + { + Collection m = metadatas.get( artifact ); + return m != null ? Collections.unmodifiableCollection( m ) : Collections.emptyList(); + } + + @Override + public void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metadata ) + { + metadatas.computeIfAbsent( artifact, a -> new CopyOnWriteArrayList<>() ).add( metadata ); + } + + @Override + public boolean isSnapshot( String version ) + { + return version.endsWith( SNAPSHOT ) || SNAPSHOT_TIMESTAMP.matcher( version ).matches(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java new file mode 100644 index 000000000000..bc5b58b3dc19 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java @@ -0,0 +1,73 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; + +import java.util.Objects; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactResolverException; +import org.apache.maven.api.services.ArtifactResolverRequest; +import org.apache.maven.api.services.ArtifactResolverResult; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.resolution.ArtifactRequest; +import org.eclipse.aether.resolution.ArtifactResolutionException; +import org.eclipse.aether.resolution.ArtifactResult; + +public class DefaultArtifactResolver implements ArtifactResolver +{ + private final RepositorySystem repositorySystem; + + @Inject + DefaultArtifactResolver( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = Objects.requireNonNull( repositorySystem ); + } + + @Override + public ArtifactResolverResult resolve( ArtifactResolverRequest request ) + throws ArtifactResolverException, IllegalArgumentException + { + DefaultSession session = ( DefaultSession ) request.getSession(); + try + { + ArtifactRequest req = new ArtifactRequest() + .setArtifact( session.toArtifact( request.getArtifact() ) ) + .setRepositories( session.toRepositories( session.getRemoteRepositories() ) ); + ArtifactResult res = repositorySystem.resolveArtifact( session.getSession(), req ); + return new ArtifactResolverResult() + { + @Override + public Artifact getArtifact() + { + return session.getArtifact( res.getArtifact() ); + } + }; + } + catch ( ArtifactResolutionException e ) + { + throw new ArtifactResolverException( "Unable to resolve artifact", e ); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java new file mode 100644 index 000000000000..c3dccd60fc8c --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java @@ -0,0 +1,96 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; + +import java.util.Collection; +import java.util.Objects; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Exclusion; + +public class DefaultDependency implements Dependency +{ + private final DefaultSession session; + private final org.eclipse.aether.graph.Dependency dependency; + + public DefaultDependency( @Nonnull DefaultSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency ) + { + this.session = Objects.requireNonNull( session, "session" ); + this.dependency = Objects.requireNonNull( dependency, "dependency" ); + } + + @Nonnull + public org.eclipse.aether.graph.Dependency getDependency() + { + return dependency; + } + + @Nonnull + @Override + public Artifact getArtifact() + { + return session.getArtifact( dependency.getArtifact() ); + } + + @Nonnull + @Override + public String getScope() + { + return dependency.getScope(); + } + + @Nullable + @Override + public Boolean getOptional() + { + return dependency.getOptional(); + } + + @Nonnull + @Override + public Collection getExclusions() + { + return new MappedCollection<>( dependency.getExclusions(), this::toExclusion ); + } + + private Exclusion toExclusion( org.eclipse.aether.graph.Exclusion exclusion ) + { + return new Exclusion() + { + @Nullable + @Override + public String getGroupId() + { + return exclusion.getGroupId(); + } + + @Nullable + @Override + public String getArtifactId() + { + return exclusion.getArtifactId(); + } + }; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java new file mode 100644 index 000000000000..1a5efb2ccb5a --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java @@ -0,0 +1,93 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; +import javax.inject.Named; + +import java.util.List; + +import org.apache.maven.api.Node; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyCollectorException; +import org.apache.maven.api.services.DependencyCollectorRequest; +import org.apache.maven.api.services.DependencyCollectorResult; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.collection.CollectResult; +import org.eclipse.aether.collection.DependencyCollectionException; +import org.eclipse.aether.graph.Dependency; + +@Named +public class DefaultDependencyCollector implements DependencyCollector +{ + + private final RepositorySystem repositorySystem; + + @Inject + DefaultDependencyCollector( @Nonnull RepositorySystem repositorySystem ) + { + this.repositorySystem = repositorySystem; + } + + @Nonnull + @Override + public DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ) + throws DependencyCollectorException, IllegalArgumentException + { + DefaultSession session = ( DefaultSession ) request.getSession(); + + Artifact rootArtifact = request.getRootArtifact().map( session::toArtifact ).orElse( null ); + Dependency root = request.getRoot().map( session::toDependency ).orElse( null ); + CollectRequest collectRequest = new CollectRequest() + .setRootArtifact( rootArtifact ) + .setRoot( root != null ? root : new Dependency( rootArtifact, null ) ) + .setDependencies( session.toDependencies( request.getDependencies() ) ) + .setManagedDependencies( session.toDependencies( request.getManagedDependencies() ) ) + .setRepositories( session.toRepositories( session.getRemoteRepositories() ) ); + + try + { + final CollectResult + result = repositorySystem.collectDependencies( session.getSession(), collectRequest ); + return new DependencyCollectorResult() + { + @Override + public List getExceptions() + { + return result.getExceptions(); + } + + @Override + public Node getRoot() + { + return session.getNode( result.getRoot() ); + } + }; + } + catch ( DependencyCollectionException e ) + { + throw new DependencyCollectorException( "Unable to collect dependencies", e ); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java new file mode 100644 index 000000000000..aa83ffb7a76d --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java @@ -0,0 +1,56 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Named; + +import java.util.stream.Collectors; + +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.services.DependencyFactory; +import org.apache.maven.api.services.DependencyFactoryException; +import org.apache.maven.api.services.DependencyFactoryRequest; + +@Named +public class DefaultDependencyFactory implements DependencyFactory +{ + + @Override + public Dependency create( DependencyFactoryRequest request ) + throws DependencyFactoryException, IllegalArgumentException + { + DefaultSession session = ( DefaultSession ) request.getSession(); + return new DefaultDependency( + session, + new org.eclipse.aether.graph.Dependency( + session.toArtifact( request.getArtifact() ), + request.getScope(), + request.isOptional(), + request.getExclusions().stream().map( this::toExclusion ).collect( Collectors.toList() ) ) ); + } + + private org.eclipse.aether.graph.Exclusion toExclusion( Exclusion exclusion ) + { + return new org.eclipse.aether.graph.Exclusion( + exclusion.getGroupId(), exclusion.getArtifactId(), "*", "*" ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java new file mode 100644 index 000000000000..e52051218f53 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java @@ -0,0 +1,106 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; +import javax.inject.Named; + +import java.util.List; +import java.util.function.Predicate; + +import org.apache.maven.api.Node; +import org.apache.maven.api.services.ArtifactResolverResult; +import org.apache.maven.api.services.DependencyResolver; +import org.apache.maven.api.services.DependencyResolverException; +import org.apache.maven.api.services.DependencyResolverRequest; +import org.apache.maven.api.services.DependencyResolverResult; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.collection.CollectRequest; +import org.eclipse.aether.graph.DependencyFilter; +import org.eclipse.aether.resolution.DependencyRequest; +import org.eclipse.aether.resolution.DependencyResolutionException; +import org.eclipse.aether.resolution.DependencyResult; + +@Named +public class DefaultDependencyResolver implements DependencyResolver +{ + + private final RepositorySystem repositorySystem; + + @Inject + DefaultDependencyResolver( RepositorySystem repositorySystem ) + { + this.repositorySystem = repositorySystem; + } + + @Override + public DependencyResolverResult resolve( DependencyResolverRequest request ) + throws DependencyResolverException + { + DefaultSession session = ( DefaultSession ) request.getSession(); + + CollectRequest collectRequest = new CollectRequest() + .setRootArtifact( request.getRootArtifact().map( session::toArtifact ).orElse( null ) ) + .setRoot( request.getRoot().map( session::toDependency ).orElse( null ) ) + .setDependencies( session.toDependencies( request.getDependencies() ) ) + .setManagedDependencies( session.toDependencies( request.getManagedDependencies() ) ) + .setRepositories( session.toRepositories( request.getSession().getRemoteRepositories() ) ); + DependencyFilter filter = request.getFilter() + .map( f -> toDependencyFilter( session, f ) ) + .orElse( null ); + DependencyRequest dependencyRequest = new DependencyRequest() + .setCollectRequest( collectRequest ) + .setFilter( filter ); + + try + { + DependencyResult result = repositorySystem.resolveDependencies( session.getSession(), dependencyRequest ); + return new DependencyResolverResult() + { + @Override + public List getCollectorExceptions() + { + return result.getCollectExceptions(); + } + + @Override + public Node getRoot() + { + return session.getNode( result.getRoot() ); + } + + @Override + public List getArtifactResults() + { + return null; + } + }; + } + catch ( DependencyResolutionException e ) + { + throw new DependencyResolverException( "Unable to resolve dependencies", e ); + } + } + + private DependencyFilter toDependencyFilter( DefaultSession session, Predicate filter ) + { + return ( node, parents ) -> filter.test( session.getNode( node ) ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java new file mode 100644 index 000000000000..9372576a8afa --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java @@ -0,0 +1,67 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; + +import java.nio.file.Path; +import java.util.Objects; + +import org.apache.maven.api.LocalRepository; + +public class DefaultLocalRepository implements LocalRepository +{ + + private final org.eclipse.aether.repository.LocalRepository repository; + + @Inject + public DefaultLocalRepository( @Nonnull org.eclipse.aether.repository.LocalRepository repository ) + { + this.repository = Objects.requireNonNull( repository, "repository" ); + } + + public org.eclipse.aether.repository.LocalRepository getRepository() + { + return repository; + } + + @Nonnull + @Override + public String getId() + { + return repository.getId(); + } + + @Nonnull + @Override + public String getType() + { + return repository.getContentType(); + } + + @Nonnull + @Override + public Path getPath() + { + return repository.getBasedir().toPath(); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepositoryManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepositoryManager.java new file mode 100644 index 000000000000..450791df609f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepositoryManager.java @@ -0,0 +1,81 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Session; +import org.apache.maven.api.services.LocalRepositoryManager; + +public class DefaultLocalRepositoryManager implements LocalRepositoryManager +{ + + @Override + public Path getPathForLocalArtifact( Session session, LocalRepository local, Artifact artifact ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForLocalArtifact( s.toArtifact( artifact ) ); + return local.getPath().resolve( path ); + } + + @Override + public Path getPathForLocalMetadata( Session session, LocalRepository local, Metadata metadata ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForLocalMetadata( s.toMetadata( metadata ) ); + return local.getPath().resolve( path ); + } + + @Override + public Path getPathForRemoteArtifact( Session session, LocalRepository local, + RemoteRepository remote, Artifact artifact ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForRemoteArtifact( + s.toArtifact( artifact ), s.toRepository( remote ), null ); + return local.getPath().resolve( path ); + } + + @Override + public Path getPathForRemoteMetadata( Session session, LocalRepository local, + RemoteRepository remote, Metadata metadata ) + { + DefaultSession s = (DefaultSession) session; + String path = getManager( s, local ).getPathForRemoteMetadata( + s.toMetadata( metadata ), s.toRepository( remote ), null ); + return local.getPath().resolve( path ); + } + + private org.eclipse.aether.repository.LocalRepositoryManager getManager( + DefaultSession session, LocalRepository local ) + { + org.eclipse.aether.repository.LocalRepository repository = session.toRepository( local ); + if ( "enhanced".equals( repository.getContentType() ) ) + { + repository = new org.eclipse.aether.repository.LocalRepository( repository.getBasedir(), "" ); + } + return session.getRepositorySystem().newLocalRepositoryManager( session.getSession(), repository ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java new file mode 100644 index 000000000000..68e276f3f7ad --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java @@ -0,0 +1,113 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.net.URL; +import java.nio.file.Path; +import java.util.Objects; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.xml.ModelXmlFactory; +import org.apache.maven.api.services.xml.XmlReaderException; +import org.apache.maven.api.services.xml.XmlReaderRequest; +import org.apache.maven.api.services.xml.XmlWriterException; +import org.apache.maven.api.services.xml.XmlWriterRequest; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenXpp3ReaderEx; +import org.apache.maven.model.v4.MavenXpp3WriterEx; +import org.codehaus.plexus.util.ReaderFactory; + +public class DefaultModelXmlFactory + implements ModelXmlFactory +{ + @Override + public Model read( @Nonnull XmlReaderRequest request ) throws XmlReaderException + { + Objects.requireNonNull( request, "request can not be null" ); + Path path = request.getPath(); + URL url = request.getURL(); + Reader reader = request.getReader(); + InputStream inputStream = request.getInputStream(); + if ( path == null && url == null && reader == null && inputStream == null ) + { + throw new IllegalArgumentException( "path, url, reader or inputStream must be non null" ); + } + try + { + InputSource source = null; + if ( request.getModelId() != null || request.getLocation() != null ) + { + source = new InputSource( request.getModelId(), request.getLocation() ); + } + MavenXpp3ReaderEx xml = new MavenXpp3ReaderEx(); + xml.setAddDefaultEntities( request.isAddDefaultEntities() ); + if ( path != null ) + { + reader = ReaderFactory.newXmlReader( path.toFile() ); + } + else if ( url != null ) + { + reader = ReaderFactory.newXmlReader( url ); + } + else if ( inputStream != null ) + { + reader = ReaderFactory.newXmlReader( inputStream ); + } + return xml.read( reader, request.isStrict(), source ); + } + catch ( Exception e ) + { + throw new XmlReaderException( "Unable to read model", e ); + } + } + + @Override + public void write( XmlWriterRequest request ) throws XmlWriterException + { + Objects.requireNonNull( request, "request can not be null" ); + Model content = Objects.requireNonNull( request.getContent(), "content can not be null" ); + OutputStream outputStream = request.getOutputStream(); + Writer writer = request.getWriter(); + if ( writer == null && outputStream == null ) + { + throw new IllegalArgumentException( "writer or outputStream must be non null" ); + } + try + { + if ( writer != null ) + { + new MavenXpp3WriterEx().write( writer, content ); + } + else + { + new MavenXpp3WriterEx().write( outputStream, content ); + } + } + catch ( Exception e ) + { + throw new XmlWriterException( "Unable to write model", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java new file mode 100644 index 000000000000..375758c87847 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java @@ -0,0 +1,99 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.List; +import java.util.Optional; +import java.util.function.Predicate; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Node; +import org.apache.maven.api.NodeVisitor; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Repository; + +public class DefaultNode implements Node +{ + + private final DefaultSession session; + private final org.eclipse.aether.graph.DependencyNode node; + + public DefaultNode( DefaultSession session, + org.eclipse.aether.graph.DependencyNode node ) + { + this.session = session; + this.node = node; + } + + @Override + public Artifact getArtifact() + { + return session.getArtifact( node.getArtifact() ); + } + + @Override + public Dependency getDependency() + { + return session.getDependency( node.getDependency() ); + } + + @Override + public List getChildren() + { + return new MappedList<>( node.getChildren(), session::getNode ); + } + + @Override + public List getRemoteRepositories() + { + return new MappedList<>( node.getRepositories(), session::getRemoteRepository ); + } + + @Override + public Optional getRepository() + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public boolean accept( NodeVisitor visitor ) + { + if ( visitor.enter( this ) ) + { + for ( Node child : getChildren() ) + { + if ( !child.accept( visitor ) ) + { + break; + } + } + } + return visitor.leave( this ); + } + + @Override + public Node filter( Predicate filter ) + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java new file mode 100644 index 000000000000..365ad3d1ed32 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -0,0 +1,190 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; + +import java.io.File; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Project; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; +import org.apache.maven.project.MavenProject; + +public class DefaultProject implements Project +{ + + private final DefaultSession session; + private final MavenProject project; + + public DefaultProject( DefaultSession session, MavenProject project ) + { + this.session = session; + this.project = project; + } + + public DefaultSession getSession() + { + return session; + } + + public MavenProject getProject() + { + return project; + } + + @Nonnull + @Override + public String getGroupId() + { + return project.getGroupId(); + } + + @Nonnull + @Override + public String getArtifactId() + { + return project.getArtifactId(); + } + + @Nonnull + @Override + public String getVersion() + { + return project.getVersion(); + } + + @Nonnull + @Override + public Artifact getArtifact() + { + return session.getArtifact( RepositoryUtils.toArtifact( project.getArtifact() ) ); + } + + @Nonnull + @Override + public String getPackaging() + { + return project.getPackaging(); + } + + @Nonnull + @Override + public Model getModel() + { + return project.getModel().getDelegate(); + } + + @Nonnull + @Override + public Path getPomPath() + { + File file = project.getFile(); + return file != null ? file.toPath() : null; + } + + @Nonnull + @Override + public List getDependencies() + { + return new MappedList<>( getModel().getDependencies(), this::toDependency ); + } + + @Nonnull + @Override + public List getManagedDependencies() + { + DependencyManagement dependencyManagement = getModel().getDependencyManagement(); + if ( dependencyManagement != null ) + { + return new MappedList<>( dependencyManagement.getDependencies(), this::toDependency ); + } + return Collections.emptyList(); + } + + @Override + public boolean isExecutionRoot() + { + return project.isExecutionRoot(); + } + + private Dependency toDependency( org.apache.maven.api.model.Dependency dependency ) + { + return new Dependency() + { + @Nonnull + @Override + public Artifact getArtifact() + { + return session.createArtifact( dependency.getGroupId(), dependency.getArtifactId(), + dependency.getVersion(), null, null, dependency.getType() ); + } + + @Nonnull + @Override + public String getScope() + { + return dependency.getScope(); + } + + @Override + public Boolean getOptional() + { + return dependency.isOptional(); + } + + @Nonnull + @Override + public Collection getExclusions() + { + return new MappedCollection<>( dependency.getExclusions(), this::toExclusion ); + } + + private Exclusion toExclusion( org.apache.maven.api.model.Exclusion exclusion ) + { + return new Exclusion() + { + @Nullable + @Override + public String getGroupId() + { + return exclusion.getGroupId(); + } + + @Nullable + @Override + public String getArtifactId() + { + return exclusion.getArtifactId(); + } + }; + } + }; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java new file mode 100644 index 000000000000..98841c8340b7 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java @@ -0,0 +1,258 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import javax.inject.Inject; + +import java.io.File; +import java.io.IOException; +import java.io.InputStream; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.model.building.ModelProblem; +import org.apache.maven.model.building.ModelSource; +import org.apache.maven.project.DefaultProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingException; +import org.apache.maven.project.ProjectBuildingRequest; +import org.apache.maven.project.ProjectBuildingResult; +import org.apache.maven.api.services.ArtifactResolverResult; +import org.apache.maven.api.services.DependencyResolverResult; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.services.ProjectBuilderException; +import org.apache.maven.api.services.ProjectBuilderProblem; +import org.apache.maven.api.services.ProjectBuilderRequest; +import org.apache.maven.api.services.ProjectBuilderResult; +import org.apache.maven.api.services.ProjectBuilderSource; + +public class DefaultProjectBuilder implements ProjectBuilder +{ + + private final org.apache.maven.project.ProjectBuilder builder; + + @Inject + public DefaultProjectBuilder( org.apache.maven.project.ProjectBuilder builder ) + { + this.builder = builder; + } + + @SuppressWarnings( "MethodLength" ) + @Nonnull + @Override + public ProjectBuilderResult build( ProjectBuilderRequest request ) + throws ProjectBuilderException, IllegalArgumentException + { + DefaultSession session = ( DefaultSession ) request.getSession(); + try + { + List repositories = + session.toArtifactRepositories( session.getRemoteRepositories() ); + ProjectBuildingRequest req = new DefaultProjectBuildingRequest() + .setRepositorySession( session.getSession() ) + .setRemoteRepositories( repositories ) + .setPluginArtifactRepositories( repositories ) + .setProcessPlugins( request.isProcessPlugins() ); + ProjectBuildingResult res; + if ( request.getPath().isPresent() ) + { + Path path = request.getPath().get(); + res = builder.build( path.toFile(), req ); + } + else if ( request.getSource().isPresent() ) + { + ProjectBuilderSource source = request.getSource().get(); + ModelSource modelSource = new ModelSource() + { + @Override + public InputStream getInputStream() throws IOException + { + return source.getInputStream(); + } + + @Override + public String getLocation() + { + return source.getLocation(); + } + }; + res = builder.build( modelSource, req ); + } + else if ( request.getArtifact().isPresent() ) + { + Artifact a = request.getArtifact().get(); + org.eclipse.aether.artifact.Artifact aetherArtifact = session.toArtifact( a ); + org.apache.maven.artifact.Artifact artifact = RepositoryUtils.toArtifact( aetherArtifact ); + res = builder.build( artifact, request.isAllowStubModel(), req ); + } + else + { + throw new IllegalArgumentException( "Invalid request" ); + } + return new ProjectBuilderResult() + { + @Nonnull + @Override + public String getProjectId() + { + return res.getProjectId(); + } + + @Nonnull + @Override + public Optional getPomFile() + { + return Optional.ofNullable( res.getPomFile() ).map( File::toPath ); + } + + @Nonnull + @Override + public Optional getProject() + { + return Optional.ofNullable( res.getProject() ) + .map( session::getProject ); + } + + @Nonnull + @Override + public Collection getProblems() + { + return new MappedCollection<>( res.getProblems(), this::toProblem ); + } + + private ProjectBuilderProblem toProblem( ModelProblem problem ) + { + return new ProjectBuilderProblem() + { + @Override + public String getSource() + { + return problem.getSource(); + } + + @Override + public int getLineNumber() + { + return problem.getLineNumber(); + } + + @Override + public int getColumnNumber() + { + return problem.getColumnNumber(); + } + + @Override + public String getLocation() + { + StringBuilder buffer = new StringBuilder( 256 ); + + if ( getSource().length() > 0 ) + { + if ( buffer.length() > 0 ) + { + buffer.append( ", " ); + } + buffer.append( getSource() ); + } + + if ( getLineNumber() > 0 ) + { + if ( buffer.length() > 0 ) + { + buffer.append( ", " ); + } + buffer.append( "line " ).append( getLineNumber() ); + } + + if ( getColumnNumber() > 0 ) + { + if ( buffer.length() > 0 ) + { + buffer.append( ", " ); + } + buffer.append( "column " ).append( getColumnNumber() ); + } + + return buffer.toString(); + } + + @Override + public Exception getException() + { + return problem.getException(); + } + + @Override + public String getMessage() + { + return problem.getMessage(); + } + + @Override + public Severity getSeverity() + { + return Severity.valueOf( problem.getSeverity().name() ); + } + }; + } + + @Nonnull + @Override + public Optional getDependencyResolverResult() + { + return Optional.ofNullable( res.getDependencyResolutionResult() ) + .map( r -> new DependencyResolverResult() + { + @Override + public List getCollectorExceptions() + { + return r.getCollectionErrors(); + } + + @Override + public Node getRoot() + { + return session.getNode( r.getDependencyGraph() ); + } + + @Override + public List getArtifactResults() + { + return Collections.emptyList(); + } + } ); + } + }; + } + catch ( ProjectBuildingException e ) + { + throw new ProjectBuilderException( "Unable to build project", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java new file mode 100644 index 000000000000..78ddff441eba --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java @@ -0,0 +1,121 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Optional; +import java.util.stream.Collectors; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.ProjectManager; + +public class DefaultProjectManager implements ProjectManager +{ + + private final ArtifactManager artifactManager; + + public DefaultProjectManager( ArtifactManager artifactManager ) + { + this.artifactManager = artifactManager; + } + + @Nonnull + @Override + public Optional getPath( Project project ) + { + throw new UnsupportedOperationException(); + } + + @Nonnull + @Override + public Collection getAttachedArtifacts( Project project ) + { + DefaultSession session = ( (DefaultProject ) project ).getSession(); + Collection attached = ( ( DefaultProject ) project ).getProject().getAttachedArtifacts().stream() + .map( RepositoryUtils::toArtifact ) + .map( session::getArtifact ) + .collect( Collectors.toList() ); + return Collections.unmodifiableCollection( attached ); + } + + @Override + public void attachArtifact( Project project, Artifact artifact, Path path ) + { + ( ( DefaultProject ) project ).getProject().addAttachedArtifact( + RepositoryUtils.toArtifact( ( ( DefaultProject ) project ).getSession().toArtifact( artifact ) ) ); + artifactManager.setPath( artifact, path ); + } + + @Override + public List getCompileSourceRoots( Project project ) + { + List roots = ( ( DefaultProject ) project ).getProject().getCompileSourceRoots(); + return Collections.unmodifiableList( roots ); + } + + @Override + public void addCompileSourceRoot( Project project, String sourceRoot ) + { + List roots = ( ( DefaultProject ) project ).getProject().getCompileSourceRoots(); + roots.add( sourceRoot ); + } + + @Override + public List getTestCompileSourceRoots( Project project ) + { + List roots = ( ( DefaultProject ) project ).getProject().getTestCompileSourceRoots(); + return Collections.unmodifiableList( roots ); + } + + @Override + public void addTestCompileSourceRoot( Project project, String sourceRoot ) + { + List roots = ( ( DefaultProject ) project ).getProject().getTestCompileSourceRoots(); + roots.add( sourceRoot ); + } + + @Override + public List getRepositories( Project project ) + { + return null; + } + + @Override + public List getResolvedDependencies( Project project, ResolutionScope scope ) + { + return null; + } + + @Override + public Node getCollectedDependencies( Project project, ResolutionScope scope ) + { + return null; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRemoteRepository.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRemoteRepository.java new file mode 100644 index 000000000000..e56d54280ad9 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRemoteRepository.java @@ -0,0 +1,67 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +import org.apache.maven.api.RemoteRepository; + +public class DefaultRemoteRepository implements RemoteRepository +{ + private final org.eclipse.aether.repository.RemoteRepository repository; + + public DefaultRemoteRepository( org.eclipse.aether.repository.RemoteRepository repository ) + { + this.repository = repository; + } + + public org.eclipse.aether.repository.RemoteRepository getRepository() + { + return repository; + } + + @Nonnull + @Override + public String getId() + { + return repository.getId(); + } + + @Nonnull + @Override + public String getType() + { + return repository.getContentType(); + } + + @Nonnull + @Override + public String getUrl() + { + return repository.getUrl(); + } + + @Nonnull + @Override + public String getProtocol() + { + return repository.getProtocol(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java new file mode 100644 index 000000000000..c61774c5f016 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultRepositoryFactory.java @@ -0,0 +1,88 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.nio.file.Path; + +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.model.Repository; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.repository.RepositoryPolicy; + +public class DefaultRepositoryFactory implements RepositoryFactory +{ + + private final RepositorySystem repositorySystem; + + public DefaultRepositoryFactory( RepositorySystem repositorySystem ) + { + this.repositorySystem = repositorySystem; + } + + @Override + public LocalRepository createLocal( Path path ) + { + return new DefaultLocalRepository( new org.eclipse.aether.repository.LocalRepository( path.toFile() ) ); + } + + @Override + public RemoteRepository createRemote( String id, String url ) + { + return new DefaultRemoteRepository( + new org.eclipse.aether.repository.RemoteRepository.Builder( id, "default", url ) + .build() ); + } + + @Override + public RemoteRepository createRemote( Repository repository ) + throws IllegalArgumentException + { + return new DefaultRemoteRepository( + new org.eclipse.aether.repository.RemoteRepository.Builder( + repository.getId(), repository.getLayout(), repository.getUrl() ) + .setReleasePolicy( buildRepositoryPolicy( repository.getReleases() ) ) + .setSnapshotPolicy( buildRepositoryPolicy( repository.getSnapshots() ) ) + .build() ); + } + + public static org.eclipse.aether.repository.RepositoryPolicy buildRepositoryPolicy( + org.apache.maven.api.model.RepositoryPolicy policy ) + { + boolean enabled = true; + String updatePolicy = RepositoryPolicy.UPDATE_POLICY_DAILY; + String checksumPolicy = RepositoryPolicy.CHECKSUM_POLICY_FAIL; + if ( policy != null ) + { + enabled = policy.isEnabled(); + if ( policy.getUpdatePolicy() != null ) + { + updatePolicy = policy.getUpdatePolicy(); + } + if ( policy.getChecksumPolicy() != null ) + { + checksumPolicy = policy.getChecksumPolicy(); + } + } + return new org.eclipse.aether.repository.RepositoryPolicy( + enabled, updatePolicy, checksumPolicy ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java new file mode 100644 index 000000000000..db00e4e5600b --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -0,0 +1,525 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; + +import java.io.File; +import java.nio.file.Path; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Objects; +import java.util.Properties; +import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Supplier; +import java.util.stream.Collectors; + +import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Listener; +import org.apache.maven.api.SessionData; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.ProjectManager; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.services.ToolchainManager; +import org.apache.maven.api.services.xml.ModelXmlFactory; +import org.apache.maven.api.services.xml.SettingsXmlFactory; +import org.apache.maven.api.services.xml.ToolchainsXmlFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.project.MavenProject; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyFactory; +import org.apache.maven.api.services.DependencyResolver; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; + +public class DefaultSession implements Session +{ + + private final MavenSession mavenSession; + private final RepositorySystemSession session; + private final RepositorySystem repositorySystem; + private final List repositories; + private final org.apache.maven.project.ProjectBuilder projectBuilder; + private final MavenRepositorySystem mavenRepositorySystem; + private final DefaultToolchainManagerPrivate toolchainManagerPrivate; + private final List listeners = new CopyOnWriteArrayList<>(); + private final ArtifactManager artifactManager = new DefaultArtifactManager(); + private final ProjectManager projectManager = new DefaultProjectManager( artifactManager ); + + private final Map allNodes + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allArtifacts + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allRepositories + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allProjects + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allDependencies + = Collections.synchronizedMap( new WeakHashMap<>() ); + + public DefaultSession( @Nonnull MavenSession session, + @Nonnull RepositorySystem repositorySystem, + @Nullable List repositories, + @Nonnull org.apache.maven.project.ProjectBuilder projectBuilder, + @Nonnull MavenRepositorySystem mavenRepositorySystem, + @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate ) + { + this.mavenSession = Objects.requireNonNull( session ); + this.session = mavenSession.getRepositorySession(); + this.repositorySystem = Objects.requireNonNull( repositorySystem ); + this.repositories = repositories != null + ? repositories + : mavenSession.getRequest().getRemoteRepositories().stream() + .map( RepositoryUtils::toRepo ).map( this::getRemoteRepository ).collect( Collectors.toList() ); + this.projectBuilder = projectBuilder; + this.mavenRepositorySystem = mavenRepositorySystem; + this.toolchainManagerPrivate = toolchainManagerPrivate; + } + + MavenSession getMavenSession() + { + return null; + } + + @Nonnull + @Override + public LocalRepository getLocalRepository() + { + return new DefaultLocalRepository( session.getLocalRepository() ); + } + + @Nonnull + @Override + public List getRemoteRepositories() + { + return Collections.unmodifiableList( repositories ); + } + + @Nonnull + @Override + public Settings getSettings() + { + return mavenSession.getSettings().getDelegate(); + } + + @Nonnull + @Override + public Properties getUserProperties() + { + return mavenSession.getUserProperties(); + } + + @Nonnull + @Override + public Properties getSystemProperties() + { + return mavenSession.getSystemProperties(); + } + + @Nonnull + @Override + public SessionData getData() + { + org.eclipse.aether.SessionData data = session.getData(); + return new SessionData() + { + @Override + public void set( @Nonnull Object key, @Nullable Object value ) + { + data.set( key, value ); + } + @Override + public boolean set( @Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue ) + { + return data.set( key, oldValue, newValue ); + } + @Nullable + @Override + public Object get( @Nonnull Object key ) + { + return data.get( key ); + } + @Nullable + @Override + public Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier supplier ) + { + // return data.computeIfAbsent( key, supplier ); + Object value = data.get( key ); + if ( value == null ) + { + if ( ! data.set( key, null, supplier.get() ) ) + { + value = data.get( key ); + } + } + return value; + } + }; + } + + @Nonnull + @Override + public Session withLocalRepository( @Nonnull LocalRepository localRepository ) + { + Objects.requireNonNull( localRepository, "localRepository" ); + if ( session.getLocalRepository() != null + && Objects.equals( session.getLocalRepository().getBasedir().toPath(), + localRepository.getPath() ) ) + { + return this; + } + org.eclipse.aether.repository.LocalRepository repository = toRepository( localRepository ); + org.eclipse.aether.repository.LocalRepositoryManager localRepositoryManager + = repositorySystem.newLocalRepositoryManager( session, repository ); + + RepositorySystemSession repoSession = new DefaultRepositorySystemSession( session ) + .setLocalRepositoryManager( localRepositoryManager ); + MavenSession newSession = new MavenSession( mavenSession.getContainer(), repoSession, + mavenSession.getRequest(), mavenSession.getResult() ); + return new DefaultSession( newSession, repositorySystem, + repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + } + + @Nonnull + @Override + public Session withRemoteRepositories( @Nonnull List repositories ) + { + return new DefaultSession( mavenSession, repositorySystem, + repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + } + + @Nonnull + @Override + @SuppressWarnings( "unchecked" ) + public T getService( Class clazz ) throws NoSuchElementException + { + if ( clazz == ArtifactFactory.class ) + { + return (T) new DefaultArtifactFactory(); + } + else if ( clazz == ArtifactResolver.class ) + { + return (T) new DefaultArtifactResolver( repositorySystem ); + } + else if ( clazz == ArtifactDeployer.class ) + { + return (T) new DefaultArtifactDeployer( repositorySystem ); + } + else if ( clazz == ArtifactInstaller.class ) + { + return (T) new DefaultArtifactInstaller( repositorySystem ); + } + else if ( clazz == ArtifactManager.class ) + { + return (T) artifactManager; + } + else if ( clazz == DependencyFactory.class ) + { + return (T) new DefaultDependencyFactory(); + } + else if ( clazz == DependencyCollector.class ) + { + return (T) new DefaultDependencyCollector( repositorySystem ); + } + else if ( clazz == DependencyResolver.class ) + { + return (T) new DefaultDependencyResolver( repositorySystem ); + } + else if ( clazz == ProjectBuilder.class ) + { + return (T) new DefaultProjectBuilder( projectBuilder ); + } + else if ( clazz == ProjectManager.class ) + { + return (T) projectManager; + } + else if ( clazz == LocalRepositoryManager.class ) + { + return (T) new DefaultLocalRepositoryManager(); + } + else if ( clazz == RepositoryFactory.class ) + { + return (T) new DefaultRepositoryFactory( repositorySystem ); + } + else if ( clazz == ToolchainManager.class ) + { + return (T) new DefaultToolchainManager( toolchainManagerPrivate ); + } + else if ( clazz == ModelXmlFactory.class ) + { + return (T) new DefaultModelXmlFactory(); + } + else if ( clazz == SettingsXmlFactory.class ) + { + return (T) new DefaultSettingsXmlFactory(); + } + else if ( clazz == ToolchainsXmlFactory.class ) + { + return (T) new DefaultToolchainsXmlFactory(); + } + throw new NoSuchElementException( clazz.getName() ); + } + + public RepositorySystemSession getSession() + { + return session; + } + + public RepositorySystem getRepositorySystem() + { + return repositorySystem; + } + + public RemoteRepository getRemoteRepository( org.eclipse.aether.repository.RemoteRepository repository ) + { + return allRepositories.computeIfAbsent( repository, DefaultRemoteRepository::new ); + } + + public Node getNode( org.eclipse.aether.graph.DependencyNode node ) + { + return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n ) ); + } + + public Artifact getArtifact( org.eclipse.aether.artifact.Artifact artifact ) + { + return allArtifacts.computeIfAbsent( artifact, a -> new DefaultArtifact( this, a ) ); + } + + public Dependency getDependency( org.eclipse.aether.graph.Dependency dependency ) + { + return allDependencies.computeIfAbsent( dependency, d -> new DefaultDependency( this, d ) ); + } + + public List getProjects( List projects ) + { + return projects == null ? null : projects.stream() + .map( this::getProject ) + .collect( Collectors.toList() ); + } + + public Project getProject( MavenProject project ) + { + return allProjects.computeIfAbsent( project.getId(), id -> new DefaultProject( this, project ) ); + } + + public List toRepositories( List repositories ) + { + return repositories == null ? null : repositories.stream() + .map( this::toRepository ) + .collect( Collectors.toList() ); + } + + public org.eclipse.aether.repository.RemoteRepository toRepository( RemoteRepository repository ) + { + if ( repository instanceof DefaultRemoteRepository ) + { + return ( (DefaultRemoteRepository) repository ).getRepository(); + } + else + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + } + + public org.eclipse.aether.repository.LocalRepository toRepository( LocalRepository repository ) + { + if ( repository instanceof DefaultLocalRepository ) + { + return ( ( DefaultLocalRepository ) repository ).getRepository(); + } + else + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + } + + public List toArtifactRepositories( List repositories ) + { + return repositories == null ? null : repositories.stream() + .map( this::toArtifactRepository ) + .collect( Collectors.toList() ); + } + + private ArtifactRepository toArtifactRepository( RemoteRepository repository ) + { + if ( repository instanceof DefaultRemoteRepository ) + { + org.eclipse.aether.repository.RemoteRepository rr + = ( (DefaultRemoteRepository) repository ).getRepository(); + + try + { + return mavenRepositorySystem.createRepository( + rr.getUrl(), + rr.getId(), + rr.getPolicy( false ).isEnabled(), + rr.getPolicy( false ).getUpdatePolicy(), + rr.getPolicy( true ).isEnabled(), + rr.getPolicy( true ).getUpdatePolicy(), + rr.getPolicy( false ).getChecksumPolicy() + + ); + } + catch ( Exception e ) + { + throw new RuntimeException( "Unable to create repository", e ); + } + } + else + { + // TODO + throw new UnsupportedOperationException( "Not yet implemented" ); + } + } + + public List toDependencies( Collection dependencies ) + { + return dependencies == null ? null : dependencies.stream() + .map( this::toDependency ) + .collect( Collectors.toList() ); + } + + public org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ) + { + if ( dependency instanceof DefaultDependency ) + { + return ( ( DefaultDependency ) dependency ).getDependency(); + } + else + { + String typeId = dependency.getType(); + org.eclipse.aether.artifact.ArtifactType type = typeId != null + ? session.getArtifactTypeRegistry().get( typeId ) : null; + String extension = type != null ? type.getExtension() : null; + return new org.eclipse.aether.graph.Dependency( + new org.eclipse.aether.artifact.DefaultArtifact( + dependency.getGroupId(), + dependency.getArtifactId(), + dependency.getClassifier(), + extension, + dependency.getVersion(), + type + ), null ); + } + } + + public List toArtifacts( Collection artifacts ) + { + return artifacts == null ? null : artifacts.stream() + .map( this::toArtifact ) + .collect( Collectors.toList() ); + } + + public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact ) + { + File file = getService( ArtifactManager.class ).getPath( artifact ).map( Path::toFile ).orElse( null ); + if ( artifact instanceof DefaultArtifact ) + { + org.eclipse.aether.artifact.Artifact a = ( (DefaultArtifact) artifact ).getArtifact(); + if ( Objects.equals( file, a.getFile() ) ) + { + return a; + } + } + return new org.eclipse.aether.artifact.DefaultArtifact( + artifact.getGroupId(), + artifact.getArtifactId(), + artifact.getClassifier(), + artifact.getExtension(), + artifact.getVersion(), + null, + file + ); + } + + public org.eclipse.aether.metadata.Metadata toMetadata( Metadata metadata ) + { + /* + if ( metadata instanceof ProjectArtifactMetadata ) + { + Artifact pomArtifact = new SubArtifact( mainArtifact, "", "pom" ); + pomArtifact = pomArtifact.setFile( ( (ProjectArtifactMetadata) metadata ).getFile() ); + request.addArtifact( pomArtifact ); + } + else if ( // metadata instanceof SnapshotArtifactRepositoryMetadata || + metadata instanceof ArtifactRepositoryMetadata ) + { + // eaten, handled by repo system + } + else if ( metadata instanceof org.apache.maven.shared.transfer.metadata.ArtifactMetadata ) + { + org.apache.maven.shared.transfer.metadata.ArtifactMetadata transferMetadata = + (org.apache.maven.shared.transfer.metadata.ArtifactMetadata) metadata; + + request.addMetadata( new Maven31MetadataBridge( metadata ).setFile( transferMetadata.getFile() ) ); + } + + */ + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public void registerListener( @Nonnull Listener listener ) + { + listeners.add( listener ); + } + + @Override + public void unregisterListener( @Nonnull Listener listener ) + { + listeners.remove( listener ); + } + + @Nonnull + @Override + public Collection getListeners() + { + return Collections.unmodifiableCollection( listeners ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java new file mode 100644 index 000000000000..1bc454809c20 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -0,0 +1,75 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import org.apache.maven.api.Session; +import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.SessionData; + +@Singleton +@Named +public class DefaultSessionFactory +{ + private final RepositorySystem repositorySystem; + private final org.apache.maven.project.ProjectBuilder projectBuilder; + private final MavenRepositorySystem mavenRepositorySystem; + private final DefaultToolchainManagerPrivate toolchainManagerPrivate; + + @Inject + public DefaultSessionFactory( RepositorySystem repositorySystem, + ProjectBuilder projectBuilder, + MavenRepositorySystem mavenRepositorySystem, + DefaultToolchainManagerPrivate toolchainManagerPrivate ) + { + this.repositorySystem = repositorySystem; + this.projectBuilder = projectBuilder; + this.mavenRepositorySystem = mavenRepositorySystem; + this.toolchainManagerPrivate = toolchainManagerPrivate; + } + + public Session getSession( MavenSession mavenSession ) + { + SessionData data = mavenSession.getRepositorySession().getData(); + Session session = ( Session ) data.get( DefaultSession.class ); + if ( session == null ) + { + if ( ! data.set( DefaultSession.class, null, newSession( mavenSession ) ) ) + { + session = ( Session ) data.get( DefaultSession.class ); + } + } + return session; + } + + private Session newSession( MavenSession mavenSession ) + { + return new DefaultSession( + mavenSession, repositorySystem, null, + projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java new file mode 100644 index 000000000000..ee0329fcbe39 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSettingsXmlFactory.java @@ -0,0 +1,103 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Objects; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.xml.SettingsXmlFactory; +import org.apache.maven.api.services.xml.XmlReaderException; +import org.apache.maven.api.services.xml.XmlReaderRequest; +import org.apache.maven.api.services.xml.XmlWriterException; +import org.apache.maven.api.services.xml.XmlWriterRequest; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.v4.SettingsXpp3Reader; +import org.apache.maven.settings.v4.SettingsXpp3Writer; + +public class DefaultSettingsXmlFactory + implements SettingsXmlFactory +{ + @Override + public Settings read( @Nonnull XmlReaderRequest request ) throws XmlReaderException + { + Objects.requireNonNull( request, "request can not be null" ); + Reader reader = request.getReader(); + InputStream inputStream = request.getInputStream(); + if ( reader == null && inputStream == null ) + { + throw new IllegalArgumentException( "reader or inputStream must be non null" ); + } + try + { + InputSource source = null; + if ( request.getModelId() != null || request.getLocation() != null ) + { + source = new InputSource( request.getModelId(), request.getLocation() ); + } + SettingsXpp3Reader xml = new SettingsXpp3Reader(); + xml.setAddDefaultEntities( request.isAddDefaultEntities() ); + if ( reader != null ) + { + return xml.read( reader, request.isStrict() ); + } + else + { + return xml.read( inputStream, request.isStrict() ); + } + } + catch ( Exception e ) + { + throw new XmlReaderException( "Unable to read settings", e ); + } + } + + @Override + public void write( XmlWriterRequest request ) throws XmlWriterException + { + Objects.requireNonNull( request, "request can not be null" ); + Settings content = Objects.requireNonNull( request.getContent(), "content can not be null" ); + OutputStream outputStream = request.getOutputStream(); + Writer writer = request.getWriter(); + if ( writer == null && outputStream == null ) + { + throw new IllegalArgumentException( "writer or outputStream must be non null" ); + } + try + { + if ( writer != null ) + { + new SettingsXpp3Writer().write( writer, content ); + } + else + { + new SettingsXpp3Writer().write( outputStream, content ); + } + } + catch ( Exception e ) + { + throw new XmlWriterException( "Unable to write settings", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java new file mode 100644 index 000000000000..6c285cdab5e4 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java @@ -0,0 +1,120 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.Session; +import org.apache.maven.api.Toolchain; +import org.apache.maven.api.services.ToolchainManager; +import org.apache.maven.api.services.ToolchainManagerException; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.apache.maven.toolchain.MisconfiguredToolchainException; +import org.apache.maven.toolchain.ToolchainPrivate; + +public class DefaultToolchainManager implements ToolchainManager +{ + private final DefaultToolchainManagerPrivate toolchainManagerPrivate; + + public DefaultToolchainManager( DefaultToolchainManagerPrivate toolchainManagerPrivate ) + { + this.toolchainManagerPrivate = toolchainManagerPrivate; + } + + @Override + public List getToolchains( Session session, String type, Map requirements ) + throws ToolchainManagerException + { + MavenSession s = ( ( DefaultSession ) session ).getMavenSession(); + List toolchains = + toolchainManagerPrivate.getToolchains( s, type, requirements ); + return new MappedList<>( toolchains, this::toToolchain ); + } + + @Override + public Toolchain getToolchainFromBuildContext( Session session, String type ) + throws ToolchainManagerException + { + MavenSession s = ( ( DefaultSession ) session ).getMavenSession(); + return toToolchain( toolchainManagerPrivate.getToolchainFromBuildContext( type, s ) ); + } + + @Override + public List getToolchainsForType( Session session, String type ) + throws ToolchainManagerException + { + try + { + MavenSession s = ( (DefaultSession) session ).getMavenSession(); + ToolchainPrivate[] toolchains = toolchainManagerPrivate.getToolchainsForType( type, s ); + return new MappedList<>( Arrays.asList( toolchains ), this::toToolchain ); + } + catch ( MisconfiguredToolchainException e ) + { + throw new ToolchainManagerException( "Unable to get toochains for type " + type, e ); + } + } + + @Override + public void storeToolchainToBuildContext( Session session, Toolchain toolchain ) + throws ToolchainManagerException + { + MavenSession s = ( ( DefaultSession ) session ).getMavenSession(); + org.apache.maven.toolchain.ToolchainPrivate tc = + (org.apache.maven.toolchain.ToolchainPrivate) ( (ToolchainWrapper) toolchain ).toolchain; + toolchainManagerPrivate.storeToolchainToBuildContext( tc, s ); + } + + private Toolchain toToolchain( org.apache.maven.toolchain.Toolchain toolchain ) + { + return new ToolchainWrapper( toolchain ); + } + + private static class ToolchainWrapper implements Toolchain + { + private final org.apache.maven.toolchain.Toolchain toolchain; + + ToolchainWrapper( org.apache.maven.toolchain.Toolchain toolchain ) + { + this.toolchain = toolchain; + } + + @Override + public String getType() + { + return toolchain.getType(); + } + + @Override + public String findTool( String toolName ) + { + return toolchain.findTool( toolName ); + } + + @Override + public boolean matchesRequirements( Map requirements ) + { + return ( (ToolchainPrivate) toolchain ).matchesRequirements( requirements ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java new file mode 100644 index 000000000000..33e6db4a7820 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainsXmlFactory.java @@ -0,0 +1,103 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.util.Objects; + +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.xml.ToolchainsXmlFactory; +import org.apache.maven.api.services.xml.XmlReaderException; +import org.apache.maven.api.services.xml.XmlReaderRequest; +import org.apache.maven.api.services.xml.XmlWriterException; +import org.apache.maven.api.services.xml.XmlWriterRequest; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer; + +public class DefaultToolchainsXmlFactory + implements ToolchainsXmlFactory +{ + @Override + public PersistedToolchains read( @Nonnull XmlReaderRequest request ) throws XmlReaderException + { + Objects.requireNonNull( request, "request can not be null" ); + Reader reader = request.getReader(); + InputStream inputStream = request.getInputStream(); + if ( reader == null && inputStream == null ) + { + throw new IllegalArgumentException( "reader or inputStream must be non null" ); + } + try + { + InputSource source = null; + if ( request.getModelId() != null || request.getLocation() != null ) + { + source = new InputSource( request.getModelId(), request.getLocation() ); + } + MavenToolchainsXpp3Reader xml = new MavenToolchainsXpp3Reader(); + xml.setAddDefaultEntities( request.isAddDefaultEntities() ); + if ( reader != null ) + { + return xml.read( reader, request.isStrict() ); + } + else + { + return xml.read( inputStream, request.isStrict() ); + } + } + catch ( Exception e ) + { + throw new XmlReaderException( "Unable to read toolchains", e ); + } + } + + @Override + public void write( XmlWriterRequest request ) throws XmlWriterException + { + Objects.requireNonNull( request, "request can not be null" ); + PersistedToolchains content = Objects.requireNonNull( request.getContent(), "content can not be null" ); + OutputStream outputStream = request.getOutputStream(); + Writer writer = request.getWriter(); + if ( writer == null && outputStream == null ) + { + throw new IllegalArgumentException( "writer or outputStream must be non null" ); + } + try + { + if ( writer != null ) + { + new MavenToolchainsXpp3Writer().write( writer, content ); + } + else + { + new MavenToolchainsXpp3Writer().write( outputStream, content ); + } + } + catch ( Exception e ) + { + throw new XmlWriterException( "Unable to write toolchains", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/MappedCollection.java b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedCollection.java new file mode 100644 index 000000000000..32310800f68c --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedCollection.java @@ -0,0 +1,63 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.AbstractCollection; +import java.util.Collection; +import java.util.Iterator; +import java.util.function.Function; + +public class MappedCollection extends AbstractCollection +{ + private final Collection list; + private final Function mapper; + + public MappedCollection( Collection list, Function mapper ) + { + this.list = list; + this.mapper = mapper; + } + + @Override + public Iterator iterator() + { + Iterator it = list.iterator(); + return new Iterator() + { + @Override + public boolean hasNext() + { + return it.hasNext(); + } + + @Override + public U next() + { + return mapper.apply( it.next() ); + } + }; + } + + @Override + public int size() + { + return list.size(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/MappedList.java b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedList.java new file mode 100644 index 000000000000..e68f25941c72 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/MappedList.java @@ -0,0 +1,48 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.List; +import java.util.function.Function; + +public class MappedList extends AbstractList +{ + private final List list; + private final Function mapper; + + public MappedList( List list, Function mapper ) + { + this.list = list; + this.mapper = mapper; + } + + @Override + public U get( int index ) + { + return mapper.apply( list.get( index ) ); + } + + @Override + public int size() + { + return list.size(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java index 036b94047069..a9875b100e70 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java @@ -24,6 +24,7 @@ import java.util.Arrays; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.HashSet; import java.util.List; import java.util.Map; @@ -33,7 +34,9 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.xml.Dom; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.lifecycle.DefaultLifecycles; import org.apache.maven.lifecycle.Lifecycle; import org.apache.maven.lifecycle.LifecycleMappingDelegate; @@ -58,7 +61,6 @@ import org.apache.maven.plugin.version.PluginVersionResolutionException; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -314,46 +316,56 @@ private void finalizeMojoConfiguration( MojoExecution mojoExecution ) { MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); - Xpp3Dom executionConfiguration = mojoExecution.getConfiguration(); + Dom executionConfiguration = mojoExecution.getConfiguration(); if ( executionConfiguration == null ) { executionConfiguration = new Xpp3Dom( "configuration" ); } - Xpp3Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor ); - - Xpp3Dom finalConfiguration = new Xpp3Dom( "configuration" ); + Dom defaultConfiguration = getMojoConfiguration( mojoDescriptor ); + List children = new ArrayList<>(); if ( mojoDescriptor.getParameters() != null ) { for ( Parameter parameter : mojoDescriptor.getParameters() ) { - Xpp3Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() ); + Dom parameterConfiguration = executionConfiguration.getChild( parameter.getName() ); if ( parameterConfiguration == null ) { parameterConfiguration = executionConfiguration.getChild( parameter.getAlias() ); } - Xpp3Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() ); + Dom parameterDefaults = defaultConfiguration.getChild( parameter.getName() ); - parameterConfiguration = Xpp3Dom.mergeXpp3Dom( parameterConfiguration, parameterDefaults, - Boolean.TRUE ); + if ( parameterConfiguration != null ) + { + parameterConfiguration = parameterConfiguration.merge( parameterDefaults, Boolean.TRUE ); + } + else + { + parameterConfiguration = parameterDefaults; + } if ( parameterConfiguration != null ) { - parameterConfiguration = new Xpp3Dom( parameterConfiguration, parameter.getName() ); + Map attributes = new HashMap<>( parameterConfiguration.getAttributes() ); if ( StringUtils.isEmpty( parameterConfiguration.getAttribute( "implementation" ) ) && StringUtils.isNotEmpty( parameter.getImplementation() ) ) { - parameterConfiguration.setAttribute( "implementation", parameter.getImplementation() ); + attributes.put( "implementation", parameter.getImplementation() ); } - finalConfiguration.addChild( parameterConfiguration ); + parameterConfiguration = new Xpp3Dom( parameter.getName(), parameterConfiguration.getValue(), + attributes, parameterConfiguration.getChildren(), + parameterConfiguration.getInputLocation() ); + + children.add( parameterConfiguration ); } } } + Dom finalConfiguration = new Xpp3Dom( "configuration", null, null, children, null ); mojoExecution.setConfiguration( finalConfiguration ); } @@ -549,9 +561,9 @@ private void injectLifecycleOverlay( Map> lifecycleM { for ( MojoExecution forkedExecution : forkedExecutions ) { - Xpp3Dom forkedConfiguration = forkedExecution.getConfiguration(); + Dom forkedConfiguration = forkedExecution.getConfiguration(); - forkedConfiguration = Xpp3Dom.mergeXpp3Dom( phaseConfiguration, forkedConfiguration ); + forkedConfiguration = phaseConfiguration.merge( forkedConfiguration ); forkedExecution.setConfiguration( forkedConfiguration ); } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java index b0e3fa16c4ef..119151137ac7 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java @@ -26,6 +26,7 @@ import java.util.NoSuchElementException; import java.util.Set; +import org.apache.maven.api.xml.Dom; import org.apache.maven.lifecycle.DefaultLifecycles; import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer; import org.apache.maven.lifecycle.Lifecycle; @@ -39,7 +40,6 @@ import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -221,13 +221,16 @@ private void parseLifecyclePhaseDefinitions( Map plugins, String execution.setLocation( "phase", location ); execution.setLocation( "goals", location ); - Xpp3Dom lifecycleConfiguration = mojo.getConfiguration(); + Dom lifecycleConfiguration = mojo.getConfiguration(); if ( lifecycleConfiguration != null ) { - execution.setConfiguration( new Xpp3Dom( lifecycleConfiguration ) ); + execution.setConfiguration( lifecycleConfiguration ); } - plugin.setDependencies( mojo.getDependencies() ); + if ( mojo.getDependencies() != null ) + { + plugin.setDependencies( mojo.getDependencies() ); + } plugin.getExecutions().add( execution ); } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java index 89db25bc64bb..3899a0d9eea2 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java @@ -24,13 +24,14 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.lifecycle.MojoExecutionConfigurator; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * @since 3.3.1, MNG-5753 @@ -60,20 +61,18 @@ public void configure( MavenProject project, MojoExecution mojoExecution, boolea PluginExecution pluginExecution = findPluginExecution( mojoExecution.getExecutionId(), plugin.getExecutions() ); - Xpp3Dom pomConfiguration = null; + Dom pomConfiguration = null; if ( pluginExecution != null ) { - pomConfiguration = (Xpp3Dom) pluginExecution.getConfiguration(); + pomConfiguration = pluginExecution.getConfiguration(); } else if ( allowPluginLevelConfig ) { - pomConfiguration = (Xpp3Dom) plugin.getConfiguration(); + pomConfiguration = plugin.getConfiguration(); } - Xpp3Dom mojoConfiguration = ( pomConfiguration != null ) ? new Xpp3Dom( pomConfiguration ) : null; - - mojoConfiguration = Xpp3Dom.mergeXpp3Dom( mojoExecution.getConfiguration(), mojoConfiguration ); + Dom mojoConfiguration = Xpp3Dom.merge( mojoExecution.getConfiguration(), pomConfiguration ); mojoExecution.setConfiguration( mojoConfiguration ); } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java index a64da0490e3b..b5868e7b9218 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultProjectArtifactFactory.java @@ -50,7 +50,8 @@ public DefaultProjectArtifactFactory( ArtifactFactory artifactFactory ) public Set createArtifacts( MavenProject project ) throws InvalidDependencyVersionException { - return MavenMetadataSource.createArtifacts( artifactFactory, project.getDependencies(), null, null, project ); + return MavenMetadataSource.createArtifacts( artifactFactory, + project.getDependencies(), null, null, project ); } } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java index 053d85163e7a..4080e7b3d6a3 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/MojoDescriptorCreator.java @@ -21,13 +21,17 @@ import java.util.ArrayList; import java.util.Collection; +import java.util.Collections; +import java.util.List; import java.util.StringTokenizer; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.xml.Dom; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.BuildPluginManager; import org.apache.maven.plugin.InvalidPluginDescriptorException; @@ -47,7 +51,6 @@ import org.apache.maven.plugin.version.PluginVersionResolver; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.configuration.PlexusConfiguration; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -101,12 +104,10 @@ private Plugin findPlugin( String groupId, String artifactId, Collection public static Xpp3Dom convert( MojoDescriptor mojoDescriptor ) { - Xpp3Dom dom = new Xpp3Dom( "configuration" ); - PlexusConfiguration c = mojoDescriptor.getMojoConfiguration(); + List children = new ArrayList<>(); PlexusConfiguration[] ces = c.getChildren(); - if ( ces != null ) { for ( PlexusConfiguration ce : ces ) @@ -115,17 +116,15 @@ public static Xpp3Dom convert( MojoDescriptor mojoDescriptor ) String defaultValue = ce.getAttribute( "default-value", null ); if ( value != null || defaultValue != null ) { - Xpp3Dom e = new Xpp3Dom( ce.getName() ); - e.setValue( value ); - if ( defaultValue != null ) - { - e.setAttribute( "default-value", defaultValue ); - } - dom.addChild( e ); + Xpp3Dom e = new Xpp3Dom( ce.getName(), value, + defaultValue != null ? Collections.singletonMap( "default-value", defaultValue ) : null, + null, null ); + children.add( e ); } } } + Xpp3Dom dom = new Xpp3Dom( "configuration", null, null, children, null ); return dom; } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java index 63824e24a606..034db66a4c36 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java @@ -177,9 +177,9 @@ public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject p List unversionedPlugins = executionPlan.getMojoExecutions().stream() .map( MojoExecution::getPlugin ) - .filter( p -> p.getLocation( "version" ) != null ) // versionless cli goal (?) - .filter( p -> p.getLocation( "version" ).getSource() != null ) // versionless in pom (?) - .filter( p -> defaulModelId.equals( p.getLocation( "version" ).getSource().getModelId() ) ) + .filter( p -> p.getLocation( "version" ) != null + && p.getLocation( "version" ).getSource() != null + && p.getLocation( "version" ).getSource().getModelId().equals( defaulModelId ) ) .distinct() .map( Plugin::getArtifactId ) // managed by us, groupId is always o.a.m.plugins .collect( Collectors.toList() ); diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java b/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java index 1e274c49627b..f928c5095ea8 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/mapping/LifecycleMojo.java @@ -21,8 +21,8 @@ import java.util.List; +import org.apache.maven.api.xml.Dom; import org.apache.maven.model.Dependency; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Mojo (plugin goal) binding to a lifecycle phase. @@ -33,7 +33,7 @@ public class LifecycleMojo { private String goal; - private Xpp3Dom configuration; + private Dom configuration; private List dependencies; public String getGoal() @@ -41,7 +41,7 @@ public String getGoal() return goal; } - public Xpp3Dom getConfiguration() + public Dom getConfiguration() { return configuration; } @@ -56,7 +56,7 @@ public void setGoal( String goal ) this.goal = goal; } - public void setConfiguration( Xpp3Dom configuration ) + public void setConfiguration( Dom configuration ) { this.configuration = configuration; } diff --git a/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java b/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java index ec0800f013cf..eaaeb100cdfb 100644 --- a/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java +++ b/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java @@ -25,18 +25,19 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; import org.apache.maven.lifecycle.LifeCyclePluginAnalyzer; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.PluginManagement; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; @@ -65,11 +66,12 @@ public DefaultLifecycleBindingsInjector( LifeCyclePluginAnalyzer lifecycle ) this.lifecycle = lifecycle; } - public void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { String packaging = model.getPackaging(); - Collection defaultPlugins = lifecycle.getPluginsBoundByDefaultToAllLifecycles( packaging ); + Collection defaultPlugins = + lifecycle.getPluginsBoundByDefaultToAllLifecycles( packaging ); if ( defaultPlugins == null ) { @@ -79,12 +81,15 @@ public void injectLifecycleBindings( Model model, ModelBuildingRequest request, } else if ( !defaultPlugins.isEmpty() ) { - Model lifecycleModel = new Model(); - lifecycleModel.setBuild( new Build() ); - lifecycleModel.getBuild().getPlugins().addAll( defaultPlugins ); - - merger.merge( model, lifecycleModel ); + List plugins = defaultPlugins.stream() + .map( org.apache.maven.model.Plugin::getDelegate ) + .collect( Collectors.toList() ); + Model lifecycleModel = Model.newBuilder() + .build( Build.newBuilder().plugins( plugins ).build() ) + .build(); + model = merger.merge( model, lifecycleModel ); } + return model; } /** @@ -96,22 +101,27 @@ protected static class LifecycleBindingsMerger private static final String PLUGIN_MANAGEMENT = "plugin-management"; - public void merge( Model target, Model source ) + public Model merge( Model target, Model source ) { - if ( target.getBuild() == null ) + Build targetBuild = target.getBuild(); + if ( targetBuild == null ) { - target.setBuild( new Build() ); + targetBuild = Build.newInstance(); } Map context = Collections.singletonMap( PLUGIN_MANAGEMENT, target.getBuild().getPluginManagement() ); - mergePluginContainer_Plugins( target.getBuild(), source.getBuild(), false, context ); + Build.Builder builder = Build.newBuilder( target.getBuild() ); + mergePluginContainer_Plugins( builder, targetBuild, source.getBuild(), false, context ); + + return target.withBuild( builder.build() ); } @SuppressWarnings( { "checkstyle:methodname" } ) @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, boolean sourceDominant, Map context ) { List src = source.getPlugins(); @@ -135,13 +145,13 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin existing = merged.get( key ); if ( existing != null ) { - mergePlugin( existing, element, sourceDominant, context ); + element = mergePlugin( existing, element, sourceDominant, context ); } else { - merged.put( key, element ); added.put( key, element ); } + merged.put( key, element ); } if ( !added.isEmpty() ) @@ -155,8 +165,8 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin addedPlugin = added.get( key ); if ( addedPlugin != null ) { - Plugin plugin = managedPlugin.clone(); - mergePlugin( plugin, addedPlugin, sourceDominant, Collections.emptyMap() ); + Plugin plugin = mergePlugin( managedPlugin, addedPlugin, + sourceDominant, Collections.emptyMap() ); merged.put( key, plugin ); } } @@ -165,18 +175,22 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta List result = new ArrayList<>( merged.values() ); - target.setPlugins( result ); + builder.plugins( result ); } } @Override - protected void mergePluginExecution( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) + protected void mergePluginExecution_Priority( PluginExecution.Builder builder, PluginExecution target, + PluginExecution source, boolean sourceDominant, + Map context ) { - super.mergePluginExecution( target, source, sourceDominant, context ); - - target.setPriority( Math.min( target.getPriority(), source.getPriority() ) ); + if ( target.getPriority() > source.getPriority() ) + { + builder.priority( source.getPriority() ); + builder.location( "priority", source.getLocation( "priority" ) ); + } } + //mergePluginExecution_Priority( builder, target, source, sourceDominant, context ); } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java b/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java index f77461fe377a..d7f6e8ad7f7f 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/CycleDetectedInPluginGraphException.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Plugin; import org.codehaus.plexus.component.composition.CycleDetectedInComponentGraphException; /** diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index 272371ade084..6f2256455fba 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -27,6 +27,7 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.plugin.MojoException; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MojoExecutionEvent; import org.apache.maven.execution.MojoExecutionListener; @@ -34,6 +35,7 @@ import org.apache.maven.model.Plugin; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.plugin.logging.Log; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.eclipse.aether.RepositorySystemSession; @@ -121,7 +123,16 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) scope.seed( MavenProject.class, project ); scope.seed( MojoExecution.class, mojoExecution ); - mojo = mavenPluginManager.getConfiguredMojo( Mojo.class, session, mojoExecution ); + if ( mojoDescriptor.isV4Api() ) + { + org.apache.maven.api.plugin.Mojo mojoV4 = mavenPluginManager.getConfiguredMojo( + org.apache.maven.api.plugin.Mojo.class, session, mojoExecution ); + mojo = new MojoWrapper( mojoV4 ); + } + else + { + mojo = mavenPluginManager.getConfiguredMojo( Mojo.class, session, mojoExecution ); + } legacySupport.setSession( session ); @@ -131,11 +142,15 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) try { MojoExecutionEvent mojoExecutionEvent = new MojoExecutionEvent( session, project, mojoExecution, mojo ); - mojoExecutionListener.beforeMojoExecution( mojoExecutionEvent ); - - mojo.execute(); - + if ( mojoDescriptor.isV4Api() ) + { + ( ( org.apache.maven.api.plugin.Mojo ) mojo ).execute(); + } + else + { + ( ( Mojo ) mojo ).execute(); + } mojoExecutionListener.afterMojoExecutionSuccess( mojoExecutionEvent ); } catch ( ClassCastException e ) @@ -150,69 +165,56 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) } catch ( PluginContainerException e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); throw new PluginExecutionException( mojoExecution, project, e ); } catch ( NoClassDefFoundError e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); ps.println( "A required class was missing while executing " + mojoDescriptor.getId() + ": " + e.getMessage() ); pluginRealm.display( ps ); - Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); - throw new PluginExecutionException( mojoExecution, project, wrapper ); } catch ( LinkageError e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); ps.println( "An API incompatibility was encountered while executing " + mojoDescriptor.getId() + ": " + e.getClass().getName() + ": " + e.getMessage() ); pluginRealm.display( ps ); - Exception wrapper = new PluginContainerException( mojoDescriptor, pluginRealm, os.toString(), e ); - throw new PluginExecutionException( mojoExecution, project, wrapper ); } catch ( ClassCastException e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); ByteArrayOutputStream os = new ByteArrayOutputStream( 1024 ); PrintStream ps = new PrintStream( os ); ps.println( "A type incompatibility occurred while executing " + mojoDescriptor.getId() + ": " + e.getMessage() ); pluginRealm.display( ps ); - throw new PluginExecutionException( mojoExecution, project, os.toString(), e ); } catch ( RuntimeException e ) { - mojoExecutionListener.afterExecutionFailure( new MojoExecutionEvent( session, project, mojoExecution, mojo, - e ) ); - + mojoExecutionListener.afterExecutionFailure( + new MojoExecutionEvent( session, project, mojoExecution, mojo, e ) ); throw e; } finally { mavenPluginManager.releaseMojo( mojo, mojoExecution ); - scope.exit(); - Thread.currentThread().setContextClassLoader( oldClassLoader ); - legacySupport.setSession( oldSession ); } } @@ -244,4 +246,37 @@ public MojoDescriptor getMojoDescriptor( Plugin plugin, String goal, List type ) } else if ( "session".equals( expression ) ) { - value = session; + if ( mojoDescriptor.isV4Api() ) + { + value = session.getSession(); + } + else + { + value = session; + } } else if ( expression.startsWith( "session" ) ) { @@ -228,7 +236,14 @@ else if ( expression.startsWith( "session" ) ) } else if ( "reactorProjects".equals( expression ) ) { - value = session.getProjects(); + if ( mojoDescriptor.isV4Api() ) + { + value = ( ( DefaultSession ) session.getSession() ).getProjects( session.getProjects() ); + } + else + { + value = session.getProjects(); + } } else if ( "mojoExecution".equals( expression ) ) { @@ -236,11 +251,25 @@ else if ( "mojoExecution".equals( expression ) ) } else if ( "project".equals( expression ) ) { - value = project; + if ( mojoDescriptor.isV4Api() ) + { + value = ( (DefaultSession) session.getSession() ).getProject( project ); + } + else + { + value = project; + } } else if ( "executedProject".equals( expression ) ) { - value = project.getExecutionProject(); + if ( mojoDescriptor.isV4Api() ) + { + value = ( (DefaultSession) session.getSession() ).getProject( project.getExecutionProject() ); + } + else + { + value = project.getExecutionProject(); + } } else if ( expression.startsWith( "project" ) || expression.startsWith( "pom" ) ) { diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 88813e6c9bdb..9da97072712b 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -20,6 +20,7 @@ */ import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.xml.Dom; import org.apache.maven.artifact.Artifact; import org.apache.maven.classrealm.ClassRealmManager; import org.apache.maven.execution.MavenSession; @@ -57,6 +58,7 @@ import org.apache.maven.project.MavenProject; import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.session.scope.internal.SessionScopeModule; +import org.apache.maven.internal.xml.XmlPlexusConfiguration; import org.codehaus.plexus.DefaultPlexusContainer; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.classworlds.realm.ClassRealm; @@ -69,12 +71,11 @@ import org.codehaus.plexus.component.repository.ComponentDescriptor; import org.codehaus.plexus.component.repository.exception.ComponentLifecycleException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; +import org.codehaus.plexus.configuration.DefaultPlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfigurationException; -import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.graph.DependencyFilter; import org.eclipse.aether.graph.DependencyNode; @@ -148,6 +149,7 @@ public class DefaultMavenPluginManager private final PluginDescriptorBuilder builder = new PluginDescriptorBuilder(); @Inject + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultMavenPluginManager( PlexusContainer container, ClassRealmManager classRealmManager, @@ -588,17 +590,17 @@ else if ( cause instanceof LinkageError ) ( (Mojo) mojo ).setLog( new MojoLogWrapper( mojoLogger ) ); } - Xpp3Dom dom = mojoExecution.getConfiguration(); + Dom dom = mojoExecution.getConfiguration(); PlexusConfiguration pomConfiguration; if ( dom == null ) { - pomConfiguration = new XmlPlexusConfiguration( "configuration" ); + pomConfiguration = new DefaultPlexusConfiguration( "configuration" ); } else { - pomConfiguration = new XmlPlexusConfiguration( dom ); + pomConfiguration = XmlPlexusConfiguration.toPlexusConfiguration( dom ); } ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution ); @@ -828,6 +830,8 @@ public ExtensionRealmCache.CacheRecord setupExtensionsRealm( MavenProject projec } } + // TODO: store plugin version + // resolve plugin artifacts List artifacts; PluginArtifactsCache.Key cacheKey = pluginArtifactsCache.createKey( plugin, null, repositories, session ); diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java b/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java index ca6079426dcf..2147d48085f1 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java @@ -77,7 +77,7 @@ public MavenProject getProject() @Override public void buildExtensionsAssembled( ModelBuildingEvent event ) { - Model model = event.getModel(); + Model model = new Model( event.getModel() ); try { diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java index f364d4cb86f6..95a5ee118978 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java @@ -21,6 +21,7 @@ import java.io.File; import java.io.IOException; +import java.nio.file.Path; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; @@ -104,6 +105,7 @@ public class DefaultProjectBuilder private final ProjectDependenciesResolver dependencyResolver; private final ModelCacheFactory modelCacheFactory; + @SuppressWarnings( "checkstyle:ParameterNumber" ) @Inject public DefaultProjectBuilder( ModelBuilder modelBuilder, @@ -260,9 +262,9 @@ private DependencyResolutionResult resolveDependencies( MavenProject project, Re return resolutionResult; } - private List getProfileIds( List profiles ) + private List getProfileIds( List profiles ) { - return profiles.stream().map( Profile::getId ).collect( Collectors.toList() ); + return profiles.stream().map( org.apache.maven.api.model.Profile::getId ).collect( Collectors.toList() ); } private ModelBuildingRequest getModelBuildingRequest( InternalConfig config ) @@ -279,7 +281,9 @@ private ModelBuildingRequest getModelBuildingRequest( InternalConfig config ) request.setValidationLevel( configuration.getValidationLevel() ); request.setProcessPlugins( configuration.isProcessPlugins() ); - request.setProfiles( configuration.getProfiles() ); + request.setProfiles( configuration.getProfiles() != null + ? configuration.getProfiles().stream().map( Profile::getDelegate ).collect( Collectors.toList() ) + : null ); request.setActiveProfileIds( configuration.getActiveProfileIds() ); request.setInactiveProfileIds( configuration.getInactiveProfileIds() ); request.setSystemProperties( configuration.getSystemProperties() ); @@ -484,7 +488,7 @@ private boolean build( List results, List noErrors = false; } - Model model = result.getFileModel().clone(); + Model model = new Model( result.getFileModel() ); poolBuilder.put( model.getPomFile().toPath(), model ); @@ -515,8 +519,8 @@ private boolean build( List results, List { ModelProblem problem = new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile - + " does not exist", ModelProblem.Severity.ERROR, ModelProblem.Version.BASE, model, -1, - -1, null ); + + " does not exist", ModelProblem.Severity.ERROR, ModelProblem.Version.BASE, + model.getDelegate(), -1, -1, null ); result.getProblems().add( problem ); noErrors = false; @@ -553,7 +557,7 @@ private boolean build( List results, List ModelProblem problem = new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile + " forms aggregation cycle " + buffer, ModelProblem.Severity.ERROR, - ModelProblem.Version.BASE, model, -1, -1, null ); + ModelProblem.Version.BASE, model.getDelegate(), -1, -1, null ); result.getProblems().add( problem ); noErrors = false; @@ -657,7 +661,7 @@ private boolean build( List results, List p } else { - project.setModel( interimResult.result.getEffectiveModel() ); + project.setModel( new Model( interimResult.result.getEffectiveModel() ) ); result = new DefaultProjectBuildingResult( project, e.getProblems(), null ); } @@ -675,10 +679,8 @@ private void initProject( MavenProject project, Map projects boolean buildParentIfNotExisting, ModelBuildingResult result, Map profilesXmls, ProjectBuildingRequest projectBuildingRequest ) { - Model model = result.getEffectiveModel(); - - project.setModel( model ); - project.setOriginalModel( result.getFileModel() ); + project.setModel( new Model( result.getEffectiveModel() ) ); + project.setOriginalModel( new Model( result.getFileModel() ) ); initParent( project, projects, buildParentIfNotExisting, result, projectBuildingRequest ); @@ -696,8 +698,8 @@ private void initProject( MavenProject project, Map projects } List activeProfiles = new ArrayList<>(); - activeProfiles.addAll( result.getActivePomProfiles( result.getModelIds().get( 0 ) ) ); - activeProfiles.addAll( result.getActiveExternalProfiles() ); + activeProfiles.addAll( Profile.profileToApiV3( result.getActivePomProfiles( result.getModelIds().get( 0 ) ) ) ); + activeProfiles.addAll( Profile.profileToApiV3( result.getActiveExternalProfiles() ) ); project.setActiveProfiles( activeProfiles ); project.setInjectedProfileIds( "external", getProfileIds( result.getActiveExternalProfiles() ) ); @@ -899,7 +901,7 @@ private void initParent( MavenProject project, Map projects, ModelBuildingResult result, ProjectBuildingRequest projectBuildingRequest ) { Model parentModel = result.getModelIds().size() > 1 && !result.getModelIds().get( 1 ).isEmpty() - ? result.getRawModel( result.getModelIds().get( 1 ) ) + ? new Model( result.getRawModel( result.getModelIds().get( 1 ) ) ) : null; if ( parentModel != null ) @@ -913,7 +915,8 @@ private void initParent( MavenProject project, Map projects, // org.apache.maven.its.mng4834:parent:0.1 String parentModelId = result.getModelIds().get( 1 ); - File parentPomFile = result.getRawModel( parentModelId ).getPomFile(); + Path parentPomPath = result.getRawModel( parentModelId ).getPomFile(); + File parentPomFile = parentPomPath != null ? parentPomPath.toFile() : null; MavenProject parent = projects.get( parentPomFile ); if ( parent == null && buildParentIfNotExisting ) { @@ -983,7 +986,7 @@ private static String inheritedGroupId( final ModelBuildingResult result, final if ( !modelId.isEmpty() ) { - final Model model = result.getRawModel( modelId ); + final Model model = new Model( result.getRawModel( modelId ) ); groupId = model.getGroupId() != null ? model.getGroupId() : inheritedGroupId( result, modelIndex + 1 ); @@ -1000,11 +1003,11 @@ private static String inheritedVersion( final ModelBuildingResult result, final if ( !modelId.isEmpty() ) { - final Model model = result.getRawModel( modelId ); - version = model.getVersion() != null - ? model.getVersion() - : inheritedVersion( result, modelIndex + 1 ); - + version = result.getRawModel( modelId ).getVersion(); + if ( version == null ) + { + version = inheritedVersion( result, modelIndex + 1 ); + } } return version; diff --git a/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java b/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java index 6880e7a5889d..1eb3e33e7977 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/ExtensionDescriptorBuilder.java @@ -19,9 +19,9 @@ * under the License. */ +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.ReaderFactory; -import org.codehaus.plexus.util.xml.Xpp3Dom; -import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import java.io.BufferedInputStream; @@ -101,7 +101,7 @@ public ExtensionDescriptor build( InputStream is ) { ExtensionDescriptor extensionDescriptor = new ExtensionDescriptor(); - Xpp3Dom dom; + Dom dom; try { dom = Xpp3DomBuilder.build( ReaderFactory.newXmlReader( is ) ); @@ -123,7 +123,7 @@ public ExtensionDescriptor build( InputStream is ) return extensionDescriptor; } - private List parseStrings( Xpp3Dom dom ) + private List parseStrings( Dom dom ) { List strings = null; @@ -131,7 +131,7 @@ private List parseStrings( Xpp3Dom dom ) { strings = new ArrayList<>(); - for ( Xpp3Dom child : dom.getChildren() ) + for ( Dom child : dom.getChildren() ) { String string = child.getValue(); if ( string != null ) diff --git a/maven-core/src/main/java/org/apache/maven/project/MavenProject.java b/maven-core/src/main/java/org/apache/maven/project/MavenProject.java index 57069a5e6a9a..92df51c5a63a 100644 --- a/maven-core/src/main/java/org/apache/maven/project/MavenProject.java +++ b/maven-core/src/main/java/org/apache/maven/project/MavenProject.java @@ -193,6 +193,11 @@ public MavenProject() setModel( model ); } + public MavenProject( org.apache.maven.api.model.Model model ) + { + this( new Model( model ) ); + } + public MavenProject( Model model ) { setModel( model ); @@ -969,11 +974,14 @@ public Xpp3Dom getGoalConfiguration( String pluginGroupId, String pluginArtifact if ( executionId != null ) { - PluginExecution execution = plugin.getExecutionsAsMap().get( executionId ); - if ( execution != null ) + for ( PluginExecution execution : plugin.getExecutions() ) { - // NOTE: The PluginConfigurationExpander already merged the plugin-level config in - dom = (Xpp3Dom) execution.getConfiguration(); + if ( executionId.equals( execution.getId() ) ) + { + // NOTE: The PluginConfigurationExpander already merged the plugin-level config in + dom = (Xpp3Dom) execution.getConfiguration(); + break; + } } } break; @@ -1549,7 +1557,8 @@ public Set createArtifacts( ArtifactFactory artifactFactory, String in ArtifactFilter filter ) throws InvalidDependencyVersionException { - return MavenMetadataSource.createArtifacts( artifactFactory, getDependencies(), inheritedScope, filter, this ); + return MavenMetadataSource.createArtifacts( artifactFactory, getModel().getDependencies(), + inheritedScope, filter, this ); } @Deprecated diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java index 9caa3e6c3f3f..9548cea9266f 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java @@ -25,11 +25,12 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; -import org.apache.maven.model.Dependency; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; import org.apache.maven.model.building.ArtifactModelSource; import org.apache.maven.model.building.FileModelSource; import org.apache.maven.model.building.ModelSource; @@ -138,7 +139,8 @@ public void addRepository( final Repository repository, boolean replace ) } List newRepositories = - Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( repository ) ); + Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( + new org.apache.maven.model.Repository( repository ) ) ); if ( ProjectBuildingRequest.RepositoryMerging.REQUEST_DOMINANT.equals( repositoryMerging ) ) { @@ -192,7 +194,7 @@ public ModelSource resolveModel( String groupId, String artifactId, String versi } @Override - public ModelSource resolveModel( final Parent parent ) + public ModelSource resolveModel( final Parent parent, AtomicReference modified ) throws UnresolvableModelException { try @@ -226,9 +228,13 @@ public ModelSource resolveModel( final Parent parent ) } - parent.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !parent.getVersion().equals( newVersion ) ) + { + modified.set( parent.withVersion( newVersion ) ); + } - return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); + return resolveModel( parent.getGroupId(), parent.getArtifactId(), newVersion ); } catch ( final VersionRangeResolutionException e ) { @@ -239,7 +245,7 @@ public ModelSource resolveModel( final Parent parent ) } @Override - public ModelSource resolveModel( final Dependency dependency ) + public ModelSource resolveModel( final Dependency dependency, AtomicReference modified ) throws UnresolvableModelException { try @@ -273,12 +279,16 @@ public ModelSource resolveModel( final Dependency dependency ) } - dependency.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !dependency.getVersion().equals( newVersion ) ) + { + modified.set( dependency.withVersion( newVersion ) ); + } if ( modelPool != null ) { Model model = - modelPool.get( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + modelPool.get( dependency.getGroupId(), dependency.getArtifactId(), newVersion ); if ( model != null ) { @@ -286,7 +296,7 @@ public ModelSource resolveModel( final Dependency dependency ) } } - return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), newVersion ); } catch ( VersionRangeResolutionException e ) { diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java b/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java index a73641034730..efeff386252f 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectSorter.java @@ -26,11 +26,12 @@ import java.util.Map; import java.util.stream.Collectors; +import org.apache.maven.api.model.Build; import org.apache.maven.artifact.ArtifactUtils; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Extension; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Extension; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Plugin; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.dag.CycleDetectedException; import org.codehaus.plexus.util.dag.DAG; @@ -107,13 +108,13 @@ public ProjectSorter( Collection projects ) MavenProject project = projectMap.get( projectId ); - for ( Dependency dependency : project.getDependencies() ) + for ( Dependency dependency : project.getModel().getDelegate().getDependencies() ) { addEdge( projectMap, vertexMap, project, projectVertex, dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), false, false ); } - Parent parent = project.getModel().getParent(); + Parent parent = project.getModel().getDelegate().getParent(); if ( parent != null ) { @@ -123,22 +124,26 @@ public ProjectSorter( Collection projects ) parent.getVersion(), true, false ); } - for ( Plugin plugin : project.getBuildPlugins() ) + Build build = project.getModel().getDelegate().getBuild(); + if ( build != null ) { - addEdge( projectMap, vertexMap, project, projectVertex, plugin.getGroupId(), - plugin.getArtifactId(), plugin.getVersion(), false, true ); - - for ( Dependency dependency : plugin.getDependencies() ) + for ( Plugin plugin : build.getPlugins() ) { - addEdge( projectMap, vertexMap, project, projectVertex, dependency.getGroupId(), - dependency.getArtifactId(), dependency.getVersion(), false, true ); + addEdge( projectMap, vertexMap, project, projectVertex, plugin.getGroupId(), + plugin.getArtifactId(), plugin.getVersion(), false, true ); + + for ( Dependency dependency : plugin.getDependencies() ) + { + addEdge( projectMap, vertexMap, project, projectVertex, dependency.getGroupId(), + dependency.getArtifactId(), dependency.getVersion(), false, true ); + } } - } - for ( Extension extension : project.getBuildExtensions() ) - { - addEdge( projectMap, vertexMap, project, projectVertex, extension.getGroupId(), - extension.getArtifactId(), extension.getVersion(), false, true ); + for ( Extension extension : build.getExtensions() ) + { + addEdge( projectMap, vertexMap, project, projectVertex, extension.getGroupId(), + extension.getArtifactId(), extension.getVersion(), false, true ); + } } } diff --git a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java index baf5e7c85071..c176a1d6f19b 100644 --- a/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java +++ b/maven-core/src/main/java/org/apache/maven/project/artifact/MavenMetadataSource.java @@ -231,9 +231,9 @@ else if ( artifact instanceof ArtifactWithDependencies ) } else { - dependencies = rel.project.getDependencies(); + dependencies = rel.project.getModel().getDependencies(); - DependencyManagement depMgmt = rel.project.getDependencyManagement(); + DependencyManagement depMgmt = rel.project.getModel().getDependencyManagement(); managedDependencies = ( depMgmt != null ) ? depMgmt.getDependencies() : null; pomRepositories = rel.project.getRemoteArtifactRepositories(); @@ -618,7 +618,7 @@ else if ( isNonTransferrablePom( e ) ) { Relocation relocation = null; - DistributionManagement distMgmt = project.getDistributionManagement(); + DistributionManagement distMgmt = project.getModel().getDistributionManagement(); if ( distMgmt != null ) { relocation = distMgmt.getRelocation(); diff --git a/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java b/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java index a3a8dd6f9d4a..8ef44448221d 100644 --- a/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/project/artifact/ProjectArtifact.java @@ -53,12 +53,12 @@ public MavenProject getProject() public List getDependencies() { - return project.getDependencies(); + return project.getModel().getDependencies(); } public List getManagedDependencies() { - DependencyManagement depMngt = project.getDependencyManagement(); + DependencyManagement depMngt = project.getModel().getDependencyManagement(); return ( depMngt != null ) ? Collections.unmodifiableList( depMngt.getDependencies() ) : Collections.emptyList(); diff --git a/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java b/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java index b00c58841ee3..ba93ad919795 100644 --- a/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java +++ b/maven-core/src/main/java/org/apache/maven/session/scope/internal/SessionScopeModule.java @@ -23,6 +23,7 @@ import javax.inject.Named; import org.apache.maven.SessionScoped; +import org.apache.maven.api.Session; import org.apache.maven.execution.MavenSession; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; @@ -62,5 +63,6 @@ protected void configure() bind( SessionScope.class ).toInstance( scope ); bind( MavenSession.class ).toProvider( SessionScope.seededKeyProvider() ).in( scope ); + bind( Session.class ).toProvider( SessionScope.seededKeyProvider() ).in( scope ); } } diff --git a/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java b/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java index 06fbb5d3a021..295bae224018 100644 --- a/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/settings/DefaultMavenSettingsBuilder.java @@ -26,6 +26,7 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.settings.Settings; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.properties.internal.SystemProperties; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; diff --git a/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java b/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java index c79a843d91a6..45bcbc368261 100644 --- a/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/settings/MavenSettingsBuilder.java @@ -22,6 +22,7 @@ import java.io.File; import java.io.IOException; +import org.apache.maven.api.settings.Settings; import org.apache.maven.execution.MavenExecutionRequest; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; diff --git a/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java b/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java index 8da696e8accc..c9ee446b5944 100644 --- a/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java +++ b/maven-core/src/main/java/org/apache/maven/settings/SettingsUtils.java @@ -19,10 +19,21 @@ * under the License. */ -import org.apache.maven.model.ActivationFile; -import org.apache.maven.settings.merge.MavenSettingsMerger; - +import java.util.ArrayList; import java.util.List; +import java.util.stream.Collectors; + +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.settings.Activation; +import org.apache.maven.api.settings.ActivationOS; +import org.apache.maven.api.settings.ActivationProperty; +import org.apache.maven.api.settings.Profile; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.RepositoryPolicy; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.merge.MavenSettingsMerger; /** * Several convenience methods to handle settings @@ -42,9 +53,9 @@ private SettingsUtils() * @param recessive * @param recessiveSourceLevel */ - public static void merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) + public static Settings merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) { - new MavenSettingsMerger().merge( dominant, recessive, recessiveSourceLevel ); + return new MavenSettingsMerger().merge( dominant, recessive, recessiveSourceLevel ); } /** @@ -53,80 +64,86 @@ public static void merge( Settings dominant, Settings recessive, String recessiv */ public static Profile convertToSettingsProfile( org.apache.maven.model.Profile modelProfile ) { - Profile profile = new Profile(); + Profile.Builder profile = Profile.newBuilder(); - profile.setId( modelProfile.getId() ); + profile.id( modelProfile.getId() ); org.apache.maven.model.Activation modelActivation = modelProfile.getActivation(); if ( modelActivation != null ) { - Activation activation = new Activation(); + Activation.Builder activation = Activation.newBuilder(); - activation.setActiveByDefault( modelActivation.isActiveByDefault() ); + activation.activeByDefault( modelActivation.isActiveByDefault() ); - activation.setJdk( modelActivation.getJdk() ); + activation.jdk( modelActivation.getJdk() ); org.apache.maven.model.ActivationProperty modelProp = modelActivation.getProperty(); if ( modelProp != null ) { - ActivationProperty prop = new ActivationProperty(); - prop.setName( modelProp.getName() ); - prop.setValue( modelProp.getValue() ); - activation.setProperty( prop ); + ActivationProperty prop = ActivationProperty.newBuilder() + .name( modelProp.getName() ) + .value( modelProp.getValue() ) + .build(); + activation.property( prop ); } org.apache.maven.model.ActivationOS modelOs = modelActivation.getOs(); if ( modelOs != null ) { - ActivationOS os = new ActivationOS(); - - os.setArch( modelOs.getArch() ); - os.setFamily( modelOs.getFamily() ); - os.setName( modelOs.getName() ); - os.setVersion( modelOs.getVersion() ); - - activation.setOs( os ); + ActivationOS os = ActivationOS.newBuilder() + .arch( modelOs.getArch() ) + .family( modelOs.getFamily() ) + .name( modelOs.getName() ) + .version( modelOs.getVersion() ) + .build(); + + activation.os( os ); } - ActivationFile modelFile = modelActivation.getFile(); + org.apache.maven.model.ActivationFile modelFile = modelActivation.getFile(); if ( modelFile != null ) { - org.apache.maven.settings.ActivationFile file = new org.apache.maven.settings.ActivationFile(); + org.apache.maven.api.settings.ActivationFile file + = org.apache.maven.api.settings.ActivationFile.newBuilder() + .exists( modelFile.getExists() ) + .missing( modelFile.getMissing() ) + .build(); - file.setExists( modelFile.getExists() ); - file.setMissing( modelFile.getMissing() ); - - activation.setFile( file ); + activation.file( file ); } - profile.setActivation( activation ); + profile.activation( activation.build() ); } - profile.setProperties( modelProfile.getProperties() ); + profile.properties( modelProfile.getProperties() ); List repos = modelProfile.getRepositories(); if ( repos != null ) { + List repositories = new ArrayList<>(); for ( org.apache.maven.model.Repository repo : repos ) { - profile.addRepository( convertToSettingsRepository( repo ) ); + repositories.add( convertToSettingsRepository( repo ) ); } + profile.repositories( repositories ); } List pluginRepos = modelProfile.getPluginRepositories(); if ( pluginRepos != null ) { + List repositories = new ArrayList<>(); for ( org.apache.maven.model.Repository pluginRepo : pluginRepos ) { - profile.addPluginRepository( convertToSettingsRepository( pluginRepo ) ); + repositories.add( convertToSettingsRepository( pluginRepo ) ); } + profile.pluginRepositories( repositories ); } - return profile; + return profile.build(); } /** @@ -135,121 +152,113 @@ public static Profile convertToSettingsProfile( org.apache.maven.model.Profile m */ public static org.apache.maven.model.Profile convertFromSettingsProfile( Profile settingsProfile ) { - org.apache.maven.model.Profile profile = new org.apache.maven.model.Profile(); + org.apache.maven.api.model.Profile.Builder profile = org.apache.maven.api.model.Profile.newBuilder(); - profile.setId( settingsProfile.getId() ); + profile.id( settingsProfile.getId() ); - profile.setSource( "settings.xml" ); + profile.location( "", new InputLocation( new InputSource( "settings.xml", null ) ) ); Activation settingsActivation = settingsProfile.getActivation(); if ( settingsActivation != null ) { - org.apache.maven.model.Activation activation = new org.apache.maven.model.Activation(); + org.apache.maven.api.model.Activation.Builder activation + = org.apache.maven.api.model.Activation.newBuilder(); - activation.setActiveByDefault( settingsActivation.isActiveByDefault() ); + activation.activeByDefault( settingsActivation.isActiveByDefault() ); - activation.setJdk( settingsActivation.getJdk() ); + activation.jdk( settingsActivation.getJdk() ); ActivationProperty settingsProp = settingsActivation.getProperty(); - if ( settingsProp != null ) { - org.apache.maven.model.ActivationProperty prop = new org.apache.maven.model.ActivationProperty(); - - prop.setName( settingsProp.getName() ); - prop.setValue( settingsProp.getValue() ); - - activation.setProperty( prop ); + activation.property( org.apache.maven.api.model.ActivationProperty.newBuilder() + .name( settingsProp.getName() ) + .value( settingsProp.getValue() ) + .build() ); } ActivationOS settingsOs = settingsActivation.getOs(); - if ( settingsOs != null ) { - org.apache.maven.model.ActivationOS os = new org.apache.maven.model.ActivationOS(); - - os.setArch( settingsOs.getArch() ); - os.setFamily( settingsOs.getFamily() ); - os.setName( settingsOs.getName() ); - os.setVersion( settingsOs.getVersion() ); - - activation.setOs( os ); + activation.os( org.apache.maven.api.model.ActivationOS.newBuilder() + .arch( settingsOs.getArch() ) + .family( settingsOs.getFamily() ) + .name( settingsOs.getName() ) + .version( settingsOs.getVersion() ) + .build() ); } - org.apache.maven.settings.ActivationFile settingsFile = settingsActivation.getFile(); - + org.apache.maven.api.settings.ActivationFile settingsFile = settingsActivation.getFile(); if ( settingsFile != null ) { - ActivationFile file = new ActivationFile(); - - file.setExists( settingsFile.getExists() ); - file.setMissing( settingsFile.getMissing() ); - - activation.setFile( file ); + activation.file( ActivationFile.newBuilder() + .exists( settingsFile.getExists() ) + .missing( settingsFile.getMissing() ) + .build() ); } - profile.setActivation( activation ); + profile.activation( activation.build() ); } - profile.setProperties( settingsProfile.getProperties() ); + profile.properties( settingsProfile.getProperties() ); List repos = settingsProfile.getRepositories(); if ( repos != null ) { - for ( Repository repo : repos ) - { - profile.addRepository( convertFromSettingsRepository( repo ) ); - } + profile.repositories( repos.stream() + .map( SettingsUtils::convertFromSettingsRepository ) + .collect( Collectors.toList() ) ); } List pluginRepos = settingsProfile.getPluginRepositories(); if ( pluginRepos != null ) { - for ( Repository pluginRepo : pluginRepos ) - { - profile.addPluginRepository( convertFromSettingsRepository( pluginRepo ) ); - } + profile.pluginRepositories( pluginRepos.stream() + .map( SettingsUtils::convertFromSettingsRepository ) + .collect( Collectors.toList() ) ); } - return profile; + return new org.apache.maven.model.Profile( profile.build() ); } /** * @param settingsRepo * @return a repository */ - private static org.apache.maven.model.Repository convertFromSettingsRepository( Repository settingsRepo ) + private static org.apache.maven.api.model.Repository convertFromSettingsRepository( Repository settingsRepo ) { - org.apache.maven.model.Repository repo = new org.apache.maven.model.Repository(); + org.apache.maven.api.model.Repository.Builder repo = org.apache.maven.api.model.Repository.newBuilder(); - repo.setId( settingsRepo.getId() ); - repo.setLayout( settingsRepo.getLayout() ); - repo.setName( settingsRepo.getName() ); - repo.setUrl( settingsRepo.getUrl() ); + repo.id( settingsRepo.getId() ); + repo.layout( settingsRepo.getLayout() ); + repo.name( settingsRepo.getName() ); + repo.url( settingsRepo.getUrl() ); if ( settingsRepo.getSnapshots() != null ) { - repo.setSnapshots( convertRepositoryPolicy( settingsRepo.getSnapshots() ) ); + repo.snapshots( convertRepositoryPolicy( settingsRepo.getSnapshots() ) ); } if ( settingsRepo.getReleases() != null ) { - repo.setReleases( convertRepositoryPolicy( settingsRepo.getReleases() ) ); + repo.releases( convertRepositoryPolicy( settingsRepo.getReleases() ) ); } - return repo; + return repo.build(); } /** * @param settingsPolicy * @return a RepositoryPolicy */ - private static org.apache.maven.model.RepositoryPolicy convertRepositoryPolicy( RepositoryPolicy settingsPolicy ) + private static org.apache.maven.api.model.RepositoryPolicy convertRepositoryPolicy( + RepositoryPolicy settingsPolicy ) { - org.apache.maven.model.RepositoryPolicy policy = new org.apache.maven.model.RepositoryPolicy(); - policy.setEnabled( settingsPolicy.isEnabled() ); - policy.setUpdatePolicy( settingsPolicy.getUpdatePolicy() ); - policy.setChecksumPolicy( settingsPolicy.getChecksumPolicy() ); + org.apache.maven.api.model.RepositoryPolicy policy = org.apache.maven.api.model.RepositoryPolicy.newBuilder() + .enabled( Boolean.toString( settingsPolicy.isEnabled() ) ) + .updatePolicy( settingsPolicy.getUpdatePolicy() ) + .checksumPolicy( settingsPolicy.getChecksumPolicy() ) + .build(); return policy; } @@ -259,21 +268,16 @@ private static org.apache.maven.model.RepositoryPolicy convertRepositoryPolicy( */ private static Repository convertToSettingsRepository( org.apache.maven.model.Repository modelRepo ) { - Repository repo = new Repository(); - - repo.setId( modelRepo.getId() ); - repo.setLayout( modelRepo.getLayout() ); - repo.setName( modelRepo.getName() ); - repo.setUrl( modelRepo.getUrl() ); - - if ( modelRepo.getSnapshots() != null ) - { - repo.setSnapshots( convertRepositoryPolicy( modelRepo.getSnapshots() ) ); - } - if ( modelRepo.getReleases() != null ) - { - repo.setReleases( convertRepositoryPolicy( modelRepo.getReleases() ) ); - } + Repository repo = Repository.newBuilder() + .id( modelRepo.getId() ) + .layout( modelRepo.getLayout() ) + .name( modelRepo.getName() ) + .url( modelRepo.getUrl() ) + .snapshots( modelRepo.getSnapshots() != null + ? convertRepositoryPolicy( modelRepo.getSnapshots() ) : null ) + .releases( modelRepo.getReleases() != null + ? convertRepositoryPolicy( modelRepo.getReleases() ) : null ) + .build(); return repo; } @@ -284,38 +288,12 @@ private static Repository convertToSettingsRepository( org.apache.maven.model.Re */ private static RepositoryPolicy convertRepositoryPolicy( org.apache.maven.model.RepositoryPolicy modelPolicy ) { - RepositoryPolicy policy = new RepositoryPolicy(); - policy.setEnabled( modelPolicy.isEnabled() ); - policy.setUpdatePolicy( modelPolicy.getUpdatePolicy() ); - policy.setChecksumPolicy( modelPolicy.getChecksumPolicy() ); + RepositoryPolicy policy = RepositoryPolicy.newBuilder() + .enabled( modelPolicy.isEnabled() ) + .updatePolicy( modelPolicy.getUpdatePolicy() ) + .checksumPolicy( modelPolicy.getUpdatePolicy() ) + .build(); return policy; } - /** - * @param settings could be null - * @return a new instance of settings or null if settings was null. - */ - public static Settings copySettings( Settings settings ) - { - if ( settings == null ) - { - return null; - } - - Settings clone = new Settings(); - clone.setActiveProfiles( settings.getActiveProfiles() ); - clone.setInteractiveMode( settings.isInteractiveMode() ); - clone.setLocalRepository( settings.getLocalRepository() ); - clone.setMirrors( settings.getMirrors() ); - clone.setModelEncoding( settings.getModelEncoding() ); - clone.setOffline( settings.isOffline() ); - clone.setPluginGroups( settings.getPluginGroups() ); - clone.setProfiles( settings.getProfiles() ); - clone.setProxies( settings.getProxies() ); - clone.setServers( settings.getServers() ); - clone.setSourceLevel( settings.getSourceLevel() ); - clone.setUsePluginRegistry( settings.isUsePluginRegistry() ); - - return clone; - } } diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java index 8b44552b1414..2b248512e817 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java @@ -25,7 +25,7 @@ import java.util.Properties; import java.util.Objects; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.slf4j.Logger; /** diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java index 74cb9c6c0b87..6b101b440d47 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java @@ -32,7 +32,7 @@ import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -89,7 +89,8 @@ public Toolchain getToolchainFromBuildContext( String type, MavenSession session @Override public List getToolchains( MavenSession session, String type, Map requirements ) { - List models = session.getRequest().getToolchains().get( type ); + List models = org.apache.maven.toolchain.model.ToolchainModel.toolchainModelToApiV4( + session.getRequest().getToolchains().get( type ) ); return selectToolchains( models, type, requirements ); } diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java index 8a90f184702a..8e16bad93316 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java @@ -28,7 +28,7 @@ import javax.inject.Singleton; import org.apache.maven.execution.MavenSession; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.slf4j.Logger; /** @@ -58,7 +58,7 @@ public DefaultToolchainManagerPrivate( Map factories ) } @Override - public ToolchainPrivate[] getToolchainsForType( String type, MavenSession context ) + public ToolchainPrivate[] getToolchainsForType( String type, MavenSession session ) throws MisconfiguredToolchainException { List toRet = new ArrayList<>(); @@ -71,7 +71,9 @@ public ToolchainPrivate[] getToolchainsForType( String type, MavenSession contex } else { - List availableToolchains = context.getRequest().getToolchains().get( type ); + List availableToolchains = + org.apache.maven.toolchain.model.ToolchainModel.toolchainModelToApiV4( + session.getRequest().getToolchains().get( type ) ); if ( availableToolchains != null ) { diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java index 84a31e4af58b..619aef6c1213 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainsBuilder.java @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java index 115eede3dea6..a91bac6c5006 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; /** * Internal toolchain factory, to prepare toolchains instances. diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java index 90e0f305635e..138bb2caa110 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java @@ -21,7 +21,7 @@ import java.util.Map; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; /** * a private contract between the toolchains plugin and the components. diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java index 4bb4052a902c..8d4a9787c4d5 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainsBuilder.java @@ -21,7 +21,7 @@ import java.io.File; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; /** * Builds the toolchains model from a previously configured filesystem path to the toolchains file. diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java b/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java index e264e601fde0..70d5f00af8f9 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.slf4j.Logger; /** diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java index 71d0a0206927..688cf9101733 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java @@ -26,14 +26,14 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.xml.Dom; import org.apache.maven.toolchain.MisconfiguredToolchainException; import org.apache.maven.toolchain.RequirementMatcher; import org.apache.maven.toolchain.RequirementMatcherFactory; import org.apache.maven.toolchain.ToolchainFactory; import org.apache.maven.toolchain.ToolchainPrivate; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.codehaus.plexus.util.FileUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,8 +92,8 @@ public ToolchainPrivate createToolchain( ToolchainModel model ) } // populate the configuration section - Xpp3Dom dom = (Xpp3Dom) model.getConfiguration(); - Xpp3Dom javahome = dom.getChild( JavaToolchainImpl.KEY_JAVAHOME ); + Dom dom = model.getConfiguration(); + Dom javahome = dom.getChild( JavaToolchainImpl.KEY_JAVAHOME ); if ( javahome == null ) { throw new MisconfiguredToolchainException( "Java toolchain without the " diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java index af5a88cc42ef..65009d3977c3 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java @@ -22,7 +22,7 @@ import java.io.File; import org.apache.maven.toolchain.DefaultToolchain; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.Os; import org.slf4j.Logger; diff --git a/maven-core/src/main/resources/META-INF/maven/extension.xml b/maven-core/src/main/resources/META-INF/maven/extension.xml index aa890cc9a6da..b6b1d3f11d33 100644 --- a/maven-core/src/main/resources/META-INF/maven/extension.xml +++ b/maven-core/src/main/resources/META-INF/maven/extension.xml @@ -22,6 +22,8 @@ under the License. + org.apache.maven.api + org.apache.maven.* org.apache.maven.artifact org.apache.maven.classrealm diff --git a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java index bb3574ae41d8..a2256ec088d3 100644 --- a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java +++ b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java @@ -195,7 +195,7 @@ protected List getRemoteRepositories() File repoDir = new File( getBasedir(), "src/test/remote-repo" ).getAbsoluteFile(); RepositoryPolicy policy = new RepositoryPolicy(); - policy.setEnabled( true ); + policy.setEnabled( Boolean.toString( true ) ); policy.setChecksumPolicy( "ignore" ); policy.setUpdatePolicy( "always" ); diff --git a/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java b/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java index 50506239fb99..a962cc18fe1e 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java +++ b/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.TransformerContext; import org.junit.jupiter.api.Test; import org.xmlunit.assertj.XmlAssert; diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java new file mode 100644 index 000000000000..d33adc1c1491 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -0,0 +1,113 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; + +import java.nio.file.Paths; +import java.util.Collections; + +import org.apache.maven.execution.DefaultMavenExecutionRequest; +import org.apache.maven.execution.MavenExecutionRequest; +import org.apache.maven.execution.MavenSession; +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Node; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.services.ProjectBuilderRequest; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.codehaus.plexus.testing.PlexusTest; +import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; +import org.eclipse.aether.repository.LocalRepository; +import org.eclipse.aether.repository.RemoteRepository; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertFalse; +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertNotSame; +import static org.junit.jupiter.api.Assertions.assertTrue; + +@PlexusTest +public class TestApi +{ + + Session session; + + @Inject + RepositorySystem repositorySystem; + + @Inject + org.apache.maven.project.ProjectBuilder projectBuilder; + + @Inject + MavenRepositorySystem mavenRepositorySystem; + + @Inject + DefaultToolchainManagerPrivate toolchainManagerPrivate; + + @BeforeEach + void setup() + { + RepositorySystemSession rss = MavenRepositorySystemUtils.newSession(); + DefaultMavenExecutionRequest mer = new DefaultMavenExecutionRequest(); + MavenSession ms = new MavenSession( null, rss, mer, null ); + DefaultSession session = new DefaultSession( ms, repositorySystem, + Collections.emptyList(), projectBuilder, + mavenRepositorySystem, toolchainManagerPrivate ); + DefaultLocalRepository localRepository = new DefaultLocalRepository( + new LocalRepository( "target/test-classes/apiv4-repo" ) ); + org.apache.maven.api.RemoteRepository remoteRepository = session.getRemoteRepository( + new RemoteRepository.Builder( "mirror", "default", + "file:target/test-classes/repo" ).build() ); + this.session = session + .withLocalRepository( localRepository ) + .withRemoteRepositories( Collections.singletonList( remoteRepository ) ); + } + + @Test + void testCreateAndResolveArtifact() throws Exception + { + Artifact artifact = session.createArtifact( "org.codehaus.plexus", "plexus-utils", "1.4.5", "pom" ); + assertFalse( artifact.getPath().isPresent() ); + + Artifact resolved = session.resolveArtifact( artifact ).getArtifact(); + assertNotSame( resolved, artifact ); + assertTrue( resolved.getPath().isPresent() ); + assertNotNull( resolved.getPath().get() ); + + Project project = session.getService( ProjectBuilder.class ).build( + ProjectBuilderRequest.builder().session( session ).path( resolved.getPath().get() ) + .processPlugins( false ).resolveDependencies( false ).build() ) + .getProject().get(); + assertNotNull( project ); + + artifact = session.createArtifact( "org.codehaus.plexus", "plexus-container-default", "1.0-alpha-32", "jar" ); + Node root = session.collectDependencies( artifact ).getRoot(); + assertNotNull( root ); + } + + +} diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestArtifactHandler.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestArtifactHandler.java new file mode 100644 index 000000000000..3db6e830e575 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestArtifactHandler.java @@ -0,0 +1,83 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.artifact.handler.ArtifactHandler; + +/** + * Assists unit testing. + * + * @author Benjamin Bentmann + */ +class TestArtifactHandler + implements ArtifactHandler +{ + + private String type; + + private String extension; + + public TestArtifactHandler( String type ) + { + this( type, type ); + } + + public TestArtifactHandler( String type, String extension ) + { + this.type = type; + this.extension = extension; + } + + public String getClassifier() + { + return null; + } + + public String getDirectory() + { + return getPackaging() + "s"; + } + + public String getExtension() + { + return extension; + } + + public String getLanguage() + { + return "java"; + } + + public String getPackaging() + { + return type; + } + + public boolean isAddedToClasspath() + { + return true; + } + + public boolean isIncludesDependencies() + { + return false; + } + +} diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestRepositorySystem.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestRepositorySystem.java new file mode 100644 index 000000000000..430b27631906 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestRepositorySystem.java @@ -0,0 +1,341 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.io.File; +import java.io.IOException; +import java.util.ArrayList; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.model.Model; +import org.apache.maven.artifact.Artifact; +import org.apache.maven.artifact.DefaultArtifact; +import org.apache.maven.artifact.InvalidRepositoryException; +import org.apache.maven.artifact.factory.ArtifactFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.artifact.repository.ArtifactRepositoryPolicy; +import org.apache.maven.artifact.repository.MavenArtifactRepository; +import org.apache.maven.artifact.repository.layout.ArtifactRepositoryLayout; +import org.apache.maven.artifact.repository.layout.DefaultRepositoryLayout; +import org.apache.maven.artifact.resolver.ArtifactResolutionRequest; +import org.apache.maven.artifact.resolver.ArtifactResolutionResult; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; +import org.apache.maven.artifact.versioning.VersionRange; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.Repository; +import org.apache.maven.model.io.ModelReader; +import org.apache.maven.project.artifact.ArtifactWithDependencies; +import org.apache.maven.repository.ArtifactDoesNotExistException; +import org.apache.maven.repository.ArtifactTransferFailedException; +import org.apache.maven.repository.ArtifactTransferListener; +import org.apache.maven.repository.RepositorySystem; +import org.apache.maven.settings.Mirror; +import org.apache.maven.settings.Proxy; +import org.apache.maven.settings.Server; +import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.StringUtils; +import org.eclipse.aether.RepositorySystemSession; + +/** + * @author Benjamin Bentmann + */ +@Named +@Singleton +public class TestRepositorySystem + implements RepositorySystem +{ + + private final ModelReader modelReader; + + private final ArtifactFactory artifactFactory; + + @Inject + public TestRepositorySystem( ModelReader modelReader, ArtifactFactory artifactFactory ) + { + this.modelReader = modelReader; + this.artifactFactory = artifactFactory; + } + + public ArtifactRepository buildArtifactRepository( Repository repository ) + throws InvalidRepositoryException + { + return new MavenArtifactRepository( repository.getId(), repository.getUrl(), new DefaultRepositoryLayout(), + new ArtifactRepositoryPolicy(), new ArtifactRepositoryPolicy() ); + } + + public Artifact createArtifact( String groupId, String artifactId, String version, String packaging ) + { + return createArtifact( groupId, artifactId, version, null, packaging ); + } + + public Artifact createArtifact( String groupId, String artifactId, String version, String scope, String type ) + { + return new DefaultArtifact( groupId, artifactId, version, scope, type, null, new TestArtifactHandler( type ) ); + } + + public ArtifactRepository createArtifactRepository( String id, String url, + ArtifactRepositoryLayout repositoryLayout, + ArtifactRepositoryPolicy snapshots, + ArtifactRepositoryPolicy releases ) + { + return new MavenArtifactRepository( id, url, repositoryLayout, snapshots, releases ); + } + + public Artifact createArtifactWithClassifier( String groupId, String artifactId, String version, String type, + String classifier ) + { + return new DefaultArtifact( groupId, artifactId, version, null, type, classifier, + new TestArtifactHandler( type ) ); + } + + public ArtifactRepository createDefaultLocalRepository() + throws InvalidRepositoryException + { + return createLocalRepository( new File( System.getProperty( "basedir", "." ), "target/local-repo" ).getAbsoluteFile() ); + } + + public ArtifactRepository createDefaultRemoteRepository() + throws InvalidRepositoryException + { + return new MavenArtifactRepository( DEFAULT_REMOTE_REPO_ID, "file://" + + new File( System.getProperty( "basedir", "." ), "src/test/remote-repo" ).getAbsoluteFile().toURI().getPath(), + new DefaultRepositoryLayout(), new ArtifactRepositoryPolicy(), + new ArtifactRepositoryPolicy() ); + } + + public Artifact createDependencyArtifact( Dependency dependency ) + { + Artifact artifact = + new DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), + dependency.getScope(), dependency.getType(), dependency.getClassifier(), + new TestArtifactHandler( dependency.getType() ) ); + + if ( Artifact.SCOPE_SYSTEM.equals( dependency.getScope() ) ) + { + artifact.setFile( new File( dependency.getSystemPath() ) ); + artifact.setResolved( true ); + } + + return artifact; + } + + public ArtifactRepository createLocalRepository( File localRepository ) + throws InvalidRepositoryException + { + return new MavenArtifactRepository( DEFAULT_LOCAL_REPO_ID, "file://" + localRepository.toURI().getPath(), + new DefaultRepositoryLayout(), new ArtifactRepositoryPolicy(), + new ArtifactRepositoryPolicy() ); + } + + public Artifact createPluginArtifact( Plugin plugin ) + { + VersionRange versionRange; + try + { + String version = plugin.getVersion(); + if ( StringUtils.isEmpty( version ) ) + { + version = "RELEASE"; + } + versionRange = VersionRange.createFromVersionSpec( version ); + } + catch ( InvalidVersionSpecificationException e ) + { + return null; + } + + return artifactFactory.createPluginArtifact( plugin.getGroupId(), plugin.getArtifactId(), versionRange ); + } + + public Artifact createProjectArtifact( String groupId, String artifactId, String version ) + { + return createArtifact( groupId, artifactId, version, "pom" ); + } + + public List getEffectiveRepositories( List repositories ) + { + return repositories; + } + + public Mirror getMirror( ArtifactRepository repository, List mirrors ) + { + return null; + } + + public void injectAuthentication( List repositories, List servers ) + { + } + + public void injectMirror( List repositories, List mirrors ) + { + } + + public void injectProxy( List repositories, List proxies ) + { + } + + public void publish( ArtifactRepository repository, File source, String remotePath, + ArtifactTransferListener transferListener ) + throws ArtifactTransferFailedException + { + // TODO Auto-generated method stub + + } + + public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) + { + ArtifactResolutionResult result = new ArtifactResolutionResult(); + + if ( request.isResolveRoot() ) + { + try + { + resolve( request.getArtifact(), request ); + result.addArtifact( request.getArtifact() ); + } + catch ( IOException e ) + { + result.addMissingArtifact( request.getArtifact() ); + } + } + + if ( request.isResolveTransitively() ) + { + Map artifacts = new LinkedHashMap<>(); + + if ( request.getArtifactDependencies() != null ) + { + for ( Artifact artifact : request.getArtifactDependencies() ) + { + artifacts.put( artifact.getDependencyConflictId(), artifact ); + } + } + + List dependencies = new ArrayList<>(); + if ( request.getArtifact() instanceof ArtifactWithDependencies ) + { + dependencies = ( (ArtifactWithDependencies) request.getArtifact() ).getDependencies(); + } + else + { + Artifact pomArtifact = + createProjectArtifact( request.getArtifact().getGroupId(), request.getArtifact().getArtifactId(), + request.getArtifact().getVersion() ); + File pomFile = + new File( request.getLocalRepository().getBasedir(), + request.getLocalRepository().pathOf( pomArtifact ) ); + + try + { + Model model = modelReader.read( pomFile, null ); + + dependencies = Dependency.dependencyToApiV3( model.getDependencies() ); + } + catch ( IOException e ) + { + e.printStackTrace(); + } + } + + for ( Dependency dependency : dependencies ) + { + Artifact artifact = createDependencyArtifact( dependency ); + if ( !artifacts.containsKey( artifact.getDependencyConflictId() ) ) + { + artifacts.put( artifact.getDependencyConflictId(), artifact ); + } + } + + for ( Artifact artifact : artifacts.values() ) + { + try + { + resolve( artifact, request ); + result.addArtifact( artifact ); + } + catch ( IOException e ) + { + result.addMissingArtifact( artifact ); + } + } + } + + return result; + } + + private void resolve( Artifact artifact, ArtifactResolutionRequest request ) + throws IOException + { + if ( Artifact.SCOPE_SYSTEM.equals( artifact.getScope() ) ) + { + return; + } + + ArtifactRepository localRepo = request.getLocalRepository(); + + File localFile = new File( localRepo.getBasedir(), localRepo.pathOf( artifact ) ); + + artifact.setFile( localFile ); + + if ( !localFile.exists() ) + { + if ( request.getRemoteRepositories().isEmpty() ) + { + throw new IOException( localFile + " does not exist and no remote repositories are configured" ); + } + + ArtifactRepository remoteRepo = request.getRemoteRepositories().get( 0 ); + + File remoteFile = new File( remoteRepo.getBasedir(), remoteRepo.pathOf( artifact ) ); + + FileUtils.copyFile( remoteFile, localFile ); + } + + artifact.setResolved( true ); + } + + public void retrieve( ArtifactRepository repository, File destination, String remotePath, + ArtifactTransferListener transferListener ) + throws ArtifactTransferFailedException, ArtifactDoesNotExistException + { + // TODO Auto-generated method stub + + } + + public void injectMirror( RepositorySystemSession session, List repositories ) + { + } + + public void injectProxy( RepositorySystemSession session, List repositories ) + { + } + + public void injectAuthentication( RepositorySystemSession session, List repositories ) + { + } + +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java b/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java index 6a112e8dbe76..79db913bb644 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/LifecycleExecutorTest.java @@ -23,6 +23,7 @@ import java.util.List; import org.apache.maven.AbstractCoreMavenComponentTestCase; +import org.apache.maven.api.xml.Dom; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MojoExecutionEvent; import org.apache.maven.execution.MojoExecutionListener; @@ -41,7 +42,6 @@ import org.apache.maven.plugin.MojoNotFoundException; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -291,7 +291,7 @@ public void testPluginConfigurationCreation() MojoDescriptor mojoDescriptor = mojoDescriptorCreator.getMojoDescriptor( "org.apache.maven.its.plugins:maven-it-plugin:0.1:java", session, session.getCurrentProject() ); - Xpp3Dom dom = MojoDescriptorCreator.convert( mojoDescriptor ); + Dom dom = MojoDescriptorCreator.convert( mojoDescriptor ); System.out.println( dom ); } diff --git a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java index 03570717153f..d848f8382ad3 100644 --- a/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java +++ b/maven-core/src/test/java/org/apache/maven/lifecycle/internal/stub/LifecycleExecutionPlanCalculatorStub.java @@ -16,6 +16,7 @@ package org.apache.maven.lifecycle.internal.stub; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.lifecycle.LifecycleNotFoundException; import org.apache.maven.lifecycle.LifecyclePhaseNotFoundException; import org.apache.maven.lifecycle.MavenExecutionPlan; @@ -38,7 +39,6 @@ import org.apache.maven.plugin.prefix.NoPluginFoundForPrefixException; import org.apache.maven.plugin.version.PluginVersionResolutionException; import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.util.xml.Xpp3Dom; import java.util.ArrayList; import java.util.Arrays; diff --git a/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java b/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java index 55b29b67ec83..da2ae4c8fabb 100644 --- a/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java +++ b/maven-core/src/test/java/org/apache/maven/project/EmptyLifecycleExecutor.java @@ -90,7 +90,7 @@ private Plugin newPlugin( String artifactId, String... goals ) { PluginExecution pluginExecution = new PluginExecution(); pluginExecution.setId( "default-" + goal ); - pluginExecution.addGoal( goal ); + pluginExecution.setGoals( Collections.singletonList( goal ) ); plugin.addExecution( pluginExecution ); } diff --git a/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java b/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java index 709b88cba365..f0ef5585e882 100644 --- a/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/ProjectModelResolverTest.java @@ -22,6 +22,7 @@ import java.io.File; import java.util.Collections; import java.util.List; +import java.util.concurrent.atomic.AtomicReference; import org.apache.maven.artifact.InvalidRepositoryException; import org.apache.maven.model.Dependency; @@ -69,7 +70,7 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNotFound() thro UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertThat( e.getMessage(), startsWith( "Could not find artifact org.apache:apache:pom:0 in central" ) ); @@ -85,7 +86,7 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNoMatchingVersi UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "No versions matched the requested parent version range '[2.0,2.1)'", e.getMessage() ); @@ -101,7 +102,7 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenUsingRangesWith UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested parent version range '[1,)' does not specify an upper bound", e.getMessage() ); @@ -115,7 +116,7 @@ public void testResolveParentSuccessfullyResolvesExistingParentWithoutRange() th parent.setArtifactId( "apache" ); parent.setVersion( "1" ); - assertNotNull( this.newModelResolver().resolveModel( parent ) ); + assertNotNull( this.newModelResolver().resolveModel( parent.getDelegate(), new AtomicReference<>() ) ); assertEquals( "1", parent.getVersion() ); } @@ -127,8 +128,9 @@ public void testResolveParentSuccessfullyResolvesExistingParentUsingHighestVersi parent.setArtifactId( "apache" ); parent.setVersion( "(,2.0)" ); - assertNotNull( this.newModelResolver().resolveModel( parent ) ); - assertEquals( "1", parent.getVersion() ); + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( parent.getDelegate(), modified ) ); + assertEquals( "1", modified.get().getVersion() ); } @Test @@ -141,7 +143,7 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNotFound() UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertThat( e.getMessage(), startsWith( "Could not find artifact org.apache:apache:pom:0 in central" ) ); @@ -157,7 +159,7 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNoMatchingV UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "No versions matched the requested dependency version range '[2.0,2.1)'", e.getMessage() ); @@ -173,7 +175,7 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenUsingRanges UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested dependency version range '[1,)' does not specify an upper bound", e.getMessage() ); @@ -187,7 +189,7 @@ public void testResolveDependencySuccessfullyResolvesExistingDependencyWithoutRa dependency.setArtifactId( "apache" ); dependency.setVersion( "1" ); - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); + assertNotNull( this.newModelResolver().resolveModel( dependency.getDelegate(), new AtomicReference<>() ) ); assertEquals( "1", dependency.getVersion() ); } @@ -199,8 +201,9 @@ public void testResolveDependencySuccessfullyResolvesExistingDependencyUsingHigh dependency.setArtifactId( "apache" ); dependency.setVersion( "(,2.0)" ); - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); - assertEquals( "1", dependency.getVersion() ); + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( dependency.getDelegate(), modified ) ); + assertEquals( "1", modified.get().getVersion() ); } private ModelResolver newModelResolver() throws Exception diff --git a/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java b/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java index ec15951059a3..621cf5fb94bd 100644 --- a/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/ProjectSorterTest.java @@ -259,6 +259,8 @@ public void testPluginDependenciesInfluenceSorting() build.addPlugin( plugin ); + declaringProject.getModel().setBuild( build ); + projects = new ProjectSorter( projects ).getSortedProjects(); assertEquals( parentProject, projects.get( 0 ) ); diff --git a/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java b/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java index f966237c33d9..687cb7d160cf 100644 --- a/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java @@ -22,6 +22,7 @@ import java.io.File; import java.util.List; +import org.apache.maven.api.xml.Dom; import org.apache.maven.model.Plugin; import org.apache.maven.model.PluginExecution; import org.apache.maven.project.AbstractMavenProjectTestCase; @@ -76,7 +77,7 @@ public void testProjectBuilder() assertEquals( "1.0", plugin.getVersion() ); - Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration(); + Dom configuration = plugin.getConfiguration(); assertEquals( "src/conf/plexus.conf", configuration.getChild( "plexusConfiguration" ).getValue() ); @@ -97,7 +98,7 @@ public void testProjectBuilder() assertEquals( "plexus:runtime", g0 ); - configuration = (Xpp3Dom) execution.getConfiguration(); + configuration = execution.getConfiguration(); assertEquals( "ContinuumPro", configuration.getChild( "plexusApplicationName" ).getValue() ); diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java index 9b204b24dc49..c596a06d3c40 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomAttributeIterator.java @@ -19,15 +19,14 @@ * under the License. */ -import java.util.ArrayList; -import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import org.apache.commons.jxpath.ri.QName; import org.apache.commons.jxpath.ri.model.NodeIterator; import org.apache.commons.jxpath.ri.model.NodePointer; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.internal.xml.Xpp3Dom; /** * An attribute iterator for JXPath to support Xpp3Dom. @@ -35,7 +34,7 @@ * @author Benjamin Bentmann */ class Xpp3DomAttributeIterator - implements NodeIterator + implements NodeIterator { private NodePointer parent; @@ -53,16 +52,9 @@ public Xpp3DomAttributeIterator( NodePointer parent, QName qname ) this.parent = parent; this.node = (Xpp3Dom) parent.getNode(); - Map map = new LinkedHashMap<>(); - for ( String name : this.node.getAttributeNames() ) - { - if ( name.equals( qname.getName() ) || "*".equals( qname.getName() ) ) - { - String value = this.node.getAttribute( name ); - map.put( name, value ); - } - } - this.attributes = new ArrayList<>( map.entrySet() ); + this.attributes = this.node.getAttributes().entrySet().stream() + .filter( a -> a.getKey().equals( qname.getName() ) || "*".equals( qname.getName() ) ) + .collect( Collectors.toList() ); } public NodePointer getNodePointer() @@ -86,4 +78,4 @@ public boolean setPosition( int position ) return attribute != null; } -} +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java index d137af548a80..6890cc77ddb0 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodeIterator.java @@ -28,6 +28,7 @@ import org.apache.commons.jxpath.ri.compiler.NodeTypeTest; import org.apache.commons.jxpath.ri.model.NodeIterator; import org.apache.commons.jxpath.ri.model.NodePointer; +import org.apache.maven.api.xml.Dom; import org.codehaus.plexus.util.StringUtils; import org.codehaus.plexus.util.xml.Xpp3Dom; @@ -44,29 +45,29 @@ class Xpp3DomNodeIterator private NodeTest test; - private Xpp3Dom node; + private Dom node; - private Xpp3Dom[] children; + private List children; - private List filteredChildren = new ArrayList<>(); + private List filteredChildren = new ArrayList<>(); private int filteredIndex; - private Xpp3Dom child; + private Dom child; private int position; public Xpp3DomNodeIterator( NodePointer parent, NodeTest test, boolean reverse, NodePointer startWith ) { this.parent = parent; - this.node = (Xpp3Dom) parent.getNode(); + this.node = (Dom) parent.getNode(); this.children = this.node.getChildren(); if ( startWith != null ) { Xpp3Dom startWithNode = (Xpp3Dom) startWith.getNode(); - for ( ; filteredIndex < children.length; filteredIndex++ ) + for ( ; filteredIndex < children.size(); filteredIndex++ ) { - if ( startWithNode.equals( children[filteredIndex] ) ) + if ( startWithNode.equals( children.get(filteredIndex) ) ) { filteredIndex++; break; @@ -104,9 +105,9 @@ public boolean setPosition( int position ) private void filterChildren( int position ) { - for ( ; position > filteredChildren.size() && filteredIndex < children.length; filteredIndex++ ) + for ( ; position > filteredChildren.size() && filteredIndex < children.size(); filteredIndex++ ) { - Xpp3Dom child = children[filteredIndex]; + Dom child = children.get(filteredIndex); if ( testNode( child ) ) { filteredChildren.add( child ); @@ -114,7 +115,7 @@ private void filterChildren( int position ) } } - private boolean testNode( Xpp3Dom node ) + private boolean testNode( Dom node ) { if ( test == null ) { diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java index 19defa142d87..81060b08dac6 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomNodePointer.java @@ -26,7 +26,7 @@ import org.apache.commons.jxpath.ri.compiler.NodeTest; import org.apache.commons.jxpath.ri.model.NodeIterator; import org.apache.commons.jxpath.ri.model.NodePointer; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; /** * A node pointer for JXPath to support Xpp3Dom. @@ -37,15 +37,15 @@ class Xpp3DomNodePointer extends NodePointer { - private Xpp3Dom node; + private Dom node; - public Xpp3DomNodePointer( Xpp3Dom node ) + public Xpp3DomNodePointer( Dom node ) { super( null ); this.node = node; } - public Xpp3DomNodePointer( NodePointer parent, Xpp3Dom node ) + public Xpp3DomNodePointer( NodePointer parent, Dom node ) { super( parent ); this.node = node; @@ -54,15 +54,14 @@ public Xpp3DomNodePointer( NodePointer parent, Xpp3Dom node ) @Override public int compareChildNodePointers( NodePointer pointer1, NodePointer pointer2 ) { - Xpp3Dom node1 = (Xpp3Dom) pointer1.getBaseValue(); - Xpp3Dom node2 = (Xpp3Dom) pointer2.getBaseValue(); + Dom node1 = (Dom) pointer1.getBaseValue(); + Dom node2 = (Dom) pointer2.getBaseValue(); if ( node1 == node2 ) { return 0; } - for ( int i = 0; i < node.getChildCount(); i++ ) + for ( Dom child : node.getChildren() ) { - Xpp3Dom child = node.getChild( i ); if ( child == node1 ) { return -1; @@ -81,7 +80,7 @@ public Object getValue() return getValue( node ); } - private static Object getValue( Xpp3Dom node ) + private static Object getValue( Dom node ) { if ( node.getValue() != null ) { @@ -90,9 +89,9 @@ private static Object getValue( Xpp3Dom node ) else { List children = new ArrayList<>(); - for ( int i = 0; i < node.getChildCount(); i++ ) + for ( Dom child : node.getChildren() ) { - children.add( getValue( node.getChild( i ) ) ); + children.add( getValue( child ) ); } return children; } @@ -131,7 +130,7 @@ public boolean isCollection() @Override public boolean isLeaf() { - return node.getChildCount() <= 0; + return node.getChildren().isEmpty(); } @Override diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java index 28c0f8ff5d1c..f2a686a2bcbf 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java @@ -24,7 +24,7 @@ import org.apache.commons.jxpath.ri.QName; import org.apache.commons.jxpath.ri.model.NodePointer; import org.apache.commons.jxpath.ri.model.NodePointerFactory; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; /** * A node pointer factory for JXPath to support Xpp3Dom. @@ -42,18 +42,18 @@ public int getOrder() public NodePointer createNodePointer( QName name, Object object, Locale locale ) { - if ( object instanceof Xpp3Dom ) + if ( object instanceof Dom ) { - return new Xpp3DomNodePointer( (Xpp3Dom) object ); + return new Xpp3DomNodePointer( (Dom) object ); } return null; } public NodePointer createNodePointer( NodePointer parent, QName name, Object object ) { - if ( object instanceof Xpp3Dom ) + if ( object instanceof Dom ) { - return new Xpp3DomNodePointer( parent, (Xpp3Dom) object ); + return new Xpp3DomNodePointer( parent, (Dom) object ); } return null; } diff --git a/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java b/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java index c95f42843f5e..7fdaef8d5de8 100644 --- a/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java +++ b/maven-core/src/test/java/org/apache/maven/repository/TestRepositorySystem.java @@ -25,6 +25,7 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; @@ -44,7 +45,7 @@ import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.Plugin; import org.apache.maven.model.Repository; import org.apache.maven.model.io.ModelReader; @@ -249,7 +250,7 @@ public ArtifactResolutionResult resolve( ArtifactResolutionRequest request ) { Model model = modelReader.read( pomFile, null ); - dependencies = model.getDependencies(); + dependencies = model.getDependencies().stream().map( Dependency::new ).collect( Collectors.toList() ); } catch ( IOException e ) { diff --git a/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java b/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java index e13382b53224..9b16403e5b86 100644 --- a/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java +++ b/maven-core/src/test/java/org/apache/maven/settings/PomConstructionWithSettingsTest.java @@ -112,7 +112,7 @@ private PomTestWrapper buildPom( String pomPath ) for ( org.apache.maven.settings.Profile rawProfile : settings.getProfiles() ) { - Profile profile = SettingsUtils.convertFromSettingsProfile( rawProfile ); + Profile profile = SettingsUtils.convertFromSettingsProfile( rawProfile.getDelegate() ); config.addProfile( profile ); } diff --git a/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java b/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java index 6943c342385d..bdbdad78a89e 100644 --- a/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java +++ b/maven-core/src/test/java/org/apache/maven/settings/SettingsUtilsTest.java @@ -20,10 +20,18 @@ */ import java.util.ArrayList; +import java.util.Arrays; import java.util.List; import java.util.Properties; import java.util.Random; +import org.apache.maven.api.settings.Activation; +import org.apache.maven.api.settings.ActivationFile; +import org.apache.maven.api.settings.ActivationOS; +import org.apache.maven.api.settings.ActivationProperty; +import org.apache.maven.api.settings.Profile; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.Settings; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -35,16 +43,17 @@ public class SettingsUtilsTest @Test public void testShouldAppendRecessivePluginGroupIds() { - Settings dominant = new Settings(); - dominant.addPluginGroup( "org.apache.maven.plugins" ); - dominant.addPluginGroup( "org.codehaus.modello" ); + Settings dominant = Settings.newBuilder() + .pluginGroups( Arrays.asList( "org.apache.maven.plugins", "org.codehaus.modello" ) ) + .build(); - Settings recessive = new Settings(); - recessive.addPluginGroup( "org.codehaus.plexus" ); + Settings recessive = Settings.newBuilder() + .pluginGroups( Arrays.asList( "org.codehaus.plexus" ) ) + .build(); - SettingsUtils.merge( dominant, recessive, Settings.GLOBAL_LEVEL ); + Settings merged = SettingsUtils.merge( dominant, recessive, Settings.GLOBAL_LEVEL ); - List pluginGroups = dominant.getPluginGroups(); + List pluginGroups = merged.getPluginGroups(); assertNotNull( pluginGroups ); assertEquals( 3, pluginGroups.size() ); @@ -57,56 +66,63 @@ public void testShouldAppendRecessivePluginGroupIds() public void testRoundTripProfiles() { Random entropy = new Random(); - Profile p = new Profile(); - p.setId( "id" + Long.toHexString( entropy.nextLong() ) ); - Activation a = new Activation(); - a.setActiveByDefault( entropy.nextBoolean() ); - a.setJdk( "jdk" + Long.toHexString( entropy.nextLong() ) ); - ActivationFile af = new ActivationFile(); - af.setExists( "exists" + Long.toHexString( entropy.nextLong() ) ); - af.setMissing( "missing" + Long.toHexString( entropy.nextLong() ) ); - a.setFile( af ); - ActivationProperty ap = new ActivationProperty(); - ap.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - ap.setValue( "value" + Long.toHexString( entropy.nextLong() ) ); - a.setProperty( ap ); - ActivationOS ao = new ActivationOS(); - ao.setArch( "arch" + Long.toHexString( entropy.nextLong() ) ); - ao.setFamily( "family" + Long.toHexString( entropy.nextLong() ) ); - ao.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - ao.setVersion( "version" + Long.toHexString( entropy.nextLong() ) ); - a.setOs( ao ); - p.setActivation( a ); + ActivationFile af = ActivationFile.newBuilder() + .exists( "exists" + Long.toHexString( entropy.nextLong() ) ) + .missing( "missing" + Long.toHexString( entropy.nextLong() ) ) + .build(); + ActivationProperty ap = ActivationProperty.newBuilder() + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .value( "value" + Long.toHexString( entropy.nextLong() ) ) + .build(); + ActivationOS ao = ActivationOS.newBuilder() + .arch( "arch" + Long.toHexString( entropy.nextLong() ) ) + .family( "family" + Long.toHexString( entropy.nextLong() ) ) + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .version( "version" + Long.toHexString( entropy.nextLong() ) ) + .build(); + Activation a = Activation.newBuilder() + .activeByDefault( entropy.nextBoolean() ) + .jdk( "jdk" + Long.toHexString( entropy.nextLong() ) ) + .file( af ) + .property( ap ) + .os( ao ) + .build(); Properties props = new Properties(); int count = entropy.nextInt( 10 ); for ( int i = 0; i < count; i++ ) { props.setProperty( "name" + Long.toHexString( entropy.nextLong() ), - "value" + Long.toHexString( entropy.nextLong() ) ); + "value" + Long.toHexString( entropy.nextLong() ) ); } - p.setProperties( props ); count = entropy.nextInt( 3 ); List repos = new ArrayList<>(); for ( int i = 0; i < count; i++ ) { - Repository r = new Repository(); - r.setId( "id" + Long.toHexString( entropy.nextLong() ) ); - r.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - r.setUrl( "url" + Long.toHexString( entropy.nextLong() ) ); + Repository r = Repository.newBuilder() + .id( "id" + Long.toHexString( entropy.nextLong() ) ) + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .url( "url" + Long.toHexString( entropy.nextLong() ) ) + .build(); repos.add( r ); } - p.setRepositories( repos ); count = entropy.nextInt( 3 ); - repos = new ArrayList<>(); + List pluginRepos = new ArrayList<>(); for ( int i = 0; i < count; i++ ) { - Repository r = new Repository(); - r.setId( "id" + Long.toHexString( entropy.nextLong() ) ); - r.setName( "name" + Long.toHexString( entropy.nextLong() ) ); - r.setUrl( "url" + Long.toHexString( entropy.nextLong() ) ); - repos.add( r ); + Repository r = Repository.newBuilder() + .id( "id" + Long.toHexString( entropy.nextLong() ) ) + .name( "name" + Long.toHexString( entropy.nextLong() ) ) + .url( "url" + Long.toHexString( entropy.nextLong() ) ) + .build(); + pluginRepos.add( r ); } - p.setPluginRepositories( repos ); + Profile p = Profile.newBuilder() + .id( "id" + Long.toHexString( entropy.nextLong() ) ) + .activation( a ) + .properties( props ) + .repositories( repos ) + .pluginRepositories( pluginRepos ) + .build(); Profile clone = SettingsUtils.convertToSettingsProfile( SettingsUtils.convertFromSettingsProfile( p ) ); @@ -127,4 +143,4 @@ public void testRoundTripProfiles() // TODO deep compare the lists } -} +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java index 8b2605af2f53..ca30fd18eee9 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java @@ -34,7 +34,7 @@ import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; -import org.apache.maven.toolchain.model.ToolchainModel; +import org.apache.maven.api.toolchain.ToolchainModel; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; @@ -86,8 +86,8 @@ public void testModelNoFactory() { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "unknown", Collections.singletonList( new ToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "unknown", Collections.singletonList( newToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); @@ -102,9 +102,9 @@ public void testModelAndFactory() { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "basic", Arrays.asList( new ToolchainModel(), new ToolchainModel() ) ); - toolchainModels.put( "rare", Collections.singletonList( new ToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "basic", Arrays.asList( newToolchainModel(), newToolchainModel() ) ); + toolchainModels.put( "rare", Collections.singletonList( newToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); @@ -118,9 +118,9 @@ public void testModelsAndFactory() { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "basic", Arrays.asList( new ToolchainModel(), new ToolchainModel() ) ); - toolchainModels.put( "rare", Collections.singletonList( new ToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "basic", Arrays.asList( newToolchainModel(), newToolchainModel() ) ); + toolchainModels.put( "rare", Collections.singletonList( newToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); @@ -135,9 +135,9 @@ public void testRequirements() { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "basic", Arrays.asList( new ToolchainModel(), new ToolchainModel() ) ); - toolchainModels.put( "rare", Collections.singletonList( new ToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "basic", Arrays.asList( newToolchainModel(), newToolchainModel() ) ); + toolchainModels.put( "rare", Collections.singletonList( newToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); ToolchainPrivate basicPrivate = mock( ToolchainPrivate.class ); @@ -149,4 +149,10 @@ public void testRequirements() assertEquals( 1, toolchains.size() ); } + + private org.apache.maven.toolchain.model.ToolchainModel newToolchainModel() + { + return new org.apache.maven.toolchain.model.ToolchainModel( ToolchainModel.newInstance() ); + } + } diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java index f335003a5489..fd6d66bb778b 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java @@ -26,10 +26,11 @@ import static org.mockito.Mockito.verify; import java.util.Collections; +import java.util.Properties; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.toolchain.java.DefaultJavaToolChain; -import org.apache.maven.toolchain.model.ToolchainModel; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.toolchain.ToolchainModel; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockitoAnnotations; @@ -73,7 +74,7 @@ public String findTool( String toolName ) @Test public void testGetModel() { - ToolchainModel model = new ToolchainModel(); + ToolchainModel model = ToolchainModel.newInstance(); DefaultToolchain toolchain = newDefaultToolchain( model ); assertEquals( model, toolchain.getModel() ); } @@ -81,11 +82,11 @@ public void testGetModel() @Test public void testGetType() { - ToolchainModel model = new ToolchainModel(); + ToolchainModel model = ToolchainModel.newInstance(); DefaultToolchain toolchain = newDefaultToolchain( model, "TYPE" ); assertEquals( "TYPE", toolchain.getType() ); - model.setType( "MODEL_TYPE" ); + model = model.withType( "MODEL_TYPE" ); toolchain = newDefaultToolchain( model ); assertEquals( "MODEL_TYPE", toolchain.getType() ); } @@ -93,7 +94,7 @@ public void testGetType() @Test public void testGetLogger() { - ToolchainModel model = new ToolchainModel(); + ToolchainModel model = ToolchainModel.newInstance(); DefaultToolchain toolchain = newDefaultToolchain( model ); assertEquals( logger, toolchain.getLog() ); } @@ -101,8 +102,8 @@ public void testGetLogger() @Test public void testMissingRequirementProperty() { - ToolchainModel model = new ToolchainModel(); - model.setType( "TYPE" ); + ToolchainModel model = ToolchainModel.newInstance(); + model = model.withType( "TYPE" ); DefaultToolchain toolchain = newDefaultToolchain( model ); assertFalse( toolchain.matchesRequirements( Collections.singletonMap( "name", "John Doe" ) ) ); @@ -113,8 +114,8 @@ public void testMissingRequirementProperty() @Test public void testNonMatchingRequirementProperty() { - ToolchainModel model = new ToolchainModel(); - model.setType( "TYPE" ); + ToolchainModel model = ToolchainModel.newInstance(); + model = model.withType( "TYPE" ); DefaultToolchain toolchain = newDefaultToolchain( model ); toolchain.addProvideToken( "name", RequirementMatcherFactory.createExactMatcher( "Jane Doe" ) ); @@ -126,25 +127,27 @@ public void testNonMatchingRequirementProperty() @Test public void testEquals() { - ToolchainModel tm1 = new ToolchainModel(); - tm1.setType( "jdk" ); - tm1.addProvide( "version", "1.5" ); - tm1.addProvide( "vendor", "sun" ); - Xpp3Dom configuration1 = new Xpp3Dom("configuration"); - Xpp3Dom jdkHome1 = new Xpp3Dom( "jdkHome" ); - jdkHome1.setValue("${env.JAVA_HOME}"); - configuration1.addChild( jdkHome1 ); - tm1.setConfiguration( configuration1 ); - - ToolchainModel tm2 = new ToolchainModel(); - tm1.setType( "jdk" ); - tm1.addProvide( "version", "1.4" ); - tm1.addProvide( "vendor", "sun" ); - Xpp3Dom configuration2 = new Xpp3Dom("configuration"); - Xpp3Dom jdkHome2 = new Xpp3Dom( "jdkHome" ); - jdkHome2.setValue("${env.JAVA_HOME}"); - configuration2.addChild( jdkHome2 ); - tm2.setConfiguration( configuration2 ); + Properties props1 = new Properties(); + props1.put( "version", "1.5" ); + props1.put( "vendor", "sun" ); + Xpp3Dom jdkHome1 = new Xpp3Dom( "jdkHome", "${env.JAVA_HOME}", null, null, null ); + Xpp3Dom configuration1 = new Xpp3Dom("configuration", null, null, Collections.singletonList( jdkHome1 ), null ); + ToolchainModel tm1 = ToolchainModel.newBuilder() + .type( "jdk" ) + .provides( props1 ) + .configuration( configuration1 ) + .build(); + + Properties props2 = new Properties(); + props2.put( "version", "1.4" ); + props2.put( "vendor", "sun" ); + Xpp3Dom jdkHome2 = new Xpp3Dom( "jdkHome", "${env.JAVA_HOME}", null, null, null ); + Xpp3Dom configuration2 = new Xpp3Dom("configuration", null, null, Collections.singletonList( jdkHome2 ), null ); + ToolchainModel tm2 = ToolchainModel.newBuilder() + .type( "jdk" ) + .provides( props2 ) + .configuration( configuration2 ) + .build(); DefaultToolchain tc1 = new DefaultJavaToolChain( tm1, null ); DefaultToolchain tc2 = new DefaultJavaToolChain( tm2, null ); diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..b99c9375a488e556208556e44230d7983d0fac50 GIT binary patch literal 31605 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 z + 4.0.0 + commons-logging + commons-logging + Logging + 1.0.3 + Commons Logging + http://jakarta.apache.org/commons/logging/ + 2001 + + + + log4j + log4j + 1.2.6 + true + + + logkit + logkit + 1.0.1 + true + + + junit + junit + 3.7 + test + + + diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom.sha1 new file mode 100644 index 000000000000..d135fea10f95 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.3/commons-logging-1.0.3.pom.sha1 @@ -0,0 +1 @@ +b7de43bb310eb1dbfd00a34cec30500fa13cb577 /home/projects/maven/repository-staging/to-ibiblio/maven2/commons-logging/commons-logging/1.0.3/commons-logging-1.0.3.pom diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4-javadoc-resources.jar.lastUpdated b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4-javadoc-resources.jar.lastUpdated new file mode 100644 index 000000000000..6dcdbc779638 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4-javadoc-resources.jar.lastUpdated @@ -0,0 +1,4 @@ +#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. +#Thu Sep 24 16:40:08 CEST 2020 +https\://repo.maven.apache.org/maven2/.lastUpdated=1600958408640 +https\://repo.maven.apache.org/maven2/.error= diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..b73a80fab641131e6fbe3ae833549efb3c540d17 GIT binary patch literal 38015 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 + 4.0.0 + commons-logging + commons-logging + Logging + 1.0.4 + Commons Logging is a thin adapter allowing configurable bridging to other, + well known logging systems. + http://jakarta.apache.org/commons/logging/ + + http://issues.apache.org/bugzilla/ + + + + + +
commons-dev@jakarta.apache.org
+
+
+
+
+ 2001 + + + Commons Dev List + commons-dev-subscribe@jakarta.apache.org + commons-dev-unsubscribe@jakarta.apache.org + http://nagoya.apache.org/eyebrowse/SummarizeList?listName=commons-dev@jakarta.apache.org + + + Commons User List + commons-user-subscribe@jakarta.apache.org + commons-user-unsubscribe@jakarta.apache.org + http://nagoya.apache.org/eyebrowse/SummarizeList?listName=commons-user@jakarta.apache.org + + + + + morgand + Morgan Delagrange + morgand at apache dot org + Apache + + Java Developer + + + + rwaldhoff + Rodney Waldhoff + rwaldhoff at apache org + Apache Software Foundation + + + craigmcc + Craig McClanahan + craigmcc at apache org + Apache Software Foundation + + + sanders + Scott Sanders + sanders at apache dot org + Apache Software Foundation + + + rdonkin + Robert Burrell Donkin + rdonkin at apache dot org + Apache Software Foundation + + + donaldp + Peter Donald + donaldp at apache dot org + + + + costin + Costin Manolache + costin at apache dot org + Apache Software Foundation + + + rsitze + Richard Sitze + rsitze at apache dot org + Apache Software Foundation + + + baliuka + Juozas Baliuka + baliuka@apache.org + + + Java Developer + + + + + + The Apache Software License, Version 2.0 + /LICENSE.txt + + + + scm:cvs:pserver:anoncvs@cvs.apache.org:/home/cvspublic:jakarta-commons/logging + http://cvs.apache.org/viewcvs/jakarta-commons/logging/ + + + The Apache Software Foundation + http://jakarta.apache.org + + + src/java + src/test + + + maven-surefire-plugin + + + **/AvalonLoggerTest.java + + + + + + + + log4j + log4j + 1.2.6 + true + + + logkit + logkit + 1.0.1 + true + + + junit + junit + 3.7 + test + + + avalon-framework + avalon-framework + 4.1.3 + true + + + + + default + Default Repository + file:///www/jakarta.apache.org/builds/jakarta-commons/logging/ + + + default + Default Site + scp://jakarta.apache.org//www/jakarta.apache.org/commons/logging/ + + + diff --git a/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom.sha1 new file mode 100644 index 000000000000..92265fb19772 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/commons-logging/1.0.4/commons-logging-1.0.4.pom.sha1 @@ -0,0 +1 @@ +7d32e7520b801cabc3dc704d2afe59d020d00c45 /home/projects/maven/repository-staging/to-ibiblio/maven2/commons-logging/commons-logging/1.0.4/commons-logging-1.0.4.pom diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom new file mode 100644 index 000000000000..9593e9e74def --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom @@ -0,0 +1,82 @@ + + + + + + 4.0.0 + + + org.apache + apache + 3 + pom + The Apache Software Foundation + + The Apache Software Foundation provides support for the Apache community of open-source software projects. + The Apache projects are characterized by a collaborative, consensus based development process, an open and + pragmatic software license, and a desire to create high quality software that leads the way in its field. + We consider ourselves not simply a group of projects sharing a server, but rather a community of developers + and users. + + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + Apache Software Foundation + http://www.apache.org/ + + http://www.apache.org/ + + + apache.snapshots + Apache Snapshot Repository + http://people.apache.org/repo/m2-snapshot-repository + + false + + + + + + + apache.releases + Apache Release Distribution Repository + scp://people.apache.org/www/people.apache.org/repo/m2-ibiblio-rsync-repository + + + apache.snapshots + Apache Development Snapshot Repository + scp://people.apache.org/www/people.apache.org/repo/m2-snapshot-repository + + + + + Apache Announce List + announce-subscribe@apache.org + announce-unsubscribe@apache.org + announce@apache.org + http://mail-archives.apache.org/mod_mbox/www-announce/ + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.md5 new file mode 100644 index 000000000000..b9d0ea16a252 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.md5 @@ -0,0 +1 @@ +c857ebbb5f303f435495e40e6c9e45a2 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.sha1 new file mode 100644 index 000000000000..ffb57bbc8b4f --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/apache/3/apache-3.pom.sha1 @@ -0,0 +1 @@ +1bc0010136a890e2fd38d901a0b7ecdf0e3f9871 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.jar new file mode 100644 index 0000000000000000000000000000000000000000..5bc9c06cc690a254df22434db0da0bd4e28e2d81 GIT binary patch literal 163984 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%0DNT{6W?|C~os$Ut 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ℜ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 + + + + + + maven-parent + org.apache.maven + 5 + + 4.0.0 + org.apache.maven.artifact + maven-artifact + 3.0-SNAPSHOT + Maven Artifact + + scm:svn:http://svn.apache.org/repos/asf/maven/artifact/trunk + scm:svn:https://svn.apache.org/repos/asf/maven/artifact/trunk + http://svn.apache.org/viewcvs.cgi/maven/artifact/trunk + + + + org.codehaus.plexus + plexus-utils + 1.4.5 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-32 + + + org.codehaus.plexus + plexus-active-collections + 1.0-beta-1 + + + org.apache.maven.wagon + wagon-provider-api + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-file + 1.0-beta-2 + test + + + easymock + easymock + 1.2_Java1.3 + test + + + + + + org.codehaus.modello + modello-maven-plugin + 1.0-alpha-17 + + 1.0.0 + src/main/mdo/metadata.mdo + + + + site-docs + pre-site + + xdoc + xsd + + + + standard + + java + xpp3-reader + xpp3-writer + + + + + + maven-surefire-plugin + + + **/testutils/** + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.md5 new file mode 100644 index 000000000000..11e353631a78 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.md5 @@ -0,0 +1 @@ +794377b5385c68c660ee9ca26e6b5cf1 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.sha1 new file mode 100644 index 000000000000..4beb688de1a2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/artifact/maven-artifact/3.0-SNAPSHOT/maven-artifact-3.0-SNAPSHOT.pom.sha1 @@ -0,0 +1 @@ +358254e73f075bcfb9d587d0da553083abd0cc45 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.jar new file mode 100644 index 0000000000000000000000000000000000000000..0272ee3cd22ef11fcaabc8d5f98b1faeec3f8865 GIT binary patch literal 4208 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 D)@AyW literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom new file mode 100644 index 000000000000..fee83c92a1e6 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom @@ -0,0 +1,73 @@ + + 4.0.0 + org.apache.maven.core.test + test-extension + jar + 1 + test-extension + + + + org.apache.maven.artifact + maven-artifact + 3.0-SNAPSHOT + + + org.codehaus.plexus + plexus-utils + 1.1 + + + org.codehaus.plexus + plexus + 1.0.11 + pom + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-16 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-16 + + + + + + + maven-assembly-plugin + 2.2-beta-2-SNAPSHOT + + + repo-assembly + package + + single + + + + repo.xml + + test-extension + true + ${pom.basedir}/../../resources/org/apache/maven/extension + true + + + + + + + + + + dummy + file:///tmp/dummy-repo + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.md5 new file mode 100644 index 000000000000..ad06718cdc09 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.md5 @@ -0,0 +1 @@ +e8f6e0f4ef9c2ed3fb185ef44165fb40 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.sha1 new file mode 100644 index 000000000000..6065ee045257 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-extension/1/test-extension-1.pom.sha1 @@ -0,0 +1 @@ +88ace5d78ee32fa0ce59714a4a42a73af3b52bd3 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.jar new file mode 100644 index 0000000000000000000000000000000000000000..04fe3846962d0991eec4c6f877dea1616c75b2c1 GIT binary patch literal 2582 zcmWIWW@h1H0D+vSAagJSN^k;cU)K;vT~9wZ{Q#&k4u))?veW9Gvoe6vbwDhFtjyQZ z&(qB{I7H9a?X&Nh(>~t1dKY=Ub+yi&Ilno`;EM5sr$stm=T7K&>pF3;KUoqsMNIpE zO2y7O-9f_MLBS<+wbqKra0^W~4ic>qJ{|NKDC1>Z>~-K#q~^)aqbsKhEEI`dKP6|v z&t+9?AK9MmiP;mw0CO1w*kwS+z<~ge1@}NfPHIJIF`7S`?*54|V`O0PWMN>C!=gGl zKer%1FEy{ESg#^CXYG`Oc`XV8ZSQNlY8jvIGgR}fez9=xS5`G6EncR^!r=S+G*)Q% z?wbAO*?+^&{}(&2k+PLo8xZ(#!mH({m)`1_oyyhp?MPPV)@`wzY_sG}Gv=-E+Mp7Z zvEq$mVdu7*z6ZK5x^!z-dS2wt_kN)v!?ri9feTA^gsQq}g}08;YOI|K-|L%(i0v z$-an_R5Ky&D>V3tBF79&hUTVavLK(E&sZL;MtpRCw2u} z@t?|;n^Y@gFFQ-_&PDYv8tw|I|H9n*=GyPkTh)>3y5PD-txt~q?IM#P|N5P6tFD@? z=sJ4u@eiH(_wVofsoIU`jMtXnTRzbI9&B(=B%k2$_1nFBIRHzzYKHMuf5Csj8wFGV-8s3bEjF}cJ8 z$jM19f?LJGzy-`1m)KjWXZ2K8C zBoi7#qJqQiyJQZR2+sa+C&I(l!r${aXHDAP8wT$#@|<(&;{BjJeS$%(%G~dAyqwb} z$=R+jJSZQ=75i*G&)#%ni}Kt^^C@qtM6;GXaNem@D5UZ_>ck9#B~wh(3VKU7Sr^|3 zG=4pN;%B0+)v~yDiPv{d~$)|4lE|Jk?kvdh} z1$VkmNmozId(i8?@sQ2zxWZTuP zrr+uq`%9O73w^tvtJ|J6x&P<#{Zj*9O0mas{O(_p`9sGdIGV4oB{(N<#ZHe)+Iccr zbG)WV@$>z?-y3?S{`Hh~YrpQQ|56by-!;j6+FJH`{w-hfmuy}%d(!1h*3|;%qBr(^ zQoX#Rooh>e>BE(CUzkg8+qGh=w_L;p0Iqy28*{~f;RZ}+UcA9o!;pDwm5yvk~ zyd9&`d-C=E+IIq-SNQ|H8JR?wao2G`uLFSq!&^rX4X-c|+OXGoAjKfCq){D6!nGmQ zfCv+?*G*vUV2ckTn*gt=V9tivk6u?nbc5`Fk3~0X&4ug|Y^5;5C5gbY3+@+KnGACX z_EH(4xerq_-ZC1uxu8-SVeU1O%q6PKhFOih)P`BUq|uQXBRueUi3qEqWjG>6uxCbu g3*G>060{hh+y#iN8Q{&z2C|G32<3pDeFWwK00pyo9RL6T literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom new file mode 100644 index 000000000000..01aaa425c550 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom @@ -0,0 +1,44 @@ + + 4.0.0 + org.apache.maven.core.test + test-lifecycle-and-artifactHandler + jar + 1 + test-lifecycle-and-artifactHandler + + + + + maven-assembly-plugin + 2.2-beta-2-SNAPSHOT + + + repo-assembly + package + + single + + + + repo.xml + + test-extension + true + ${pom.basedir}/../../resources/org/apache/maven/extension + true + + + + + + + + + + dummy + file:///tmp/dummy-repo + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.md5 new file mode 100644 index 000000000000..01d519420257 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.md5 @@ -0,0 +1 @@ +7f10427af029d20cbea57c21d1aec65e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.sha1 new file mode 100644 index 000000000000..dac1e45a9db7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/core/test/test-lifecycle-and-artifactHandler/1/test-lifecycle-and-artifactHandler-1.pom.sha1 @@ -0,0 +1 @@ +ed98c808239aefb0ec51a8b9e96f191da7fd92e6 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom new file mode 100644 index 000000000000..b41037fc7382 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom @@ -0,0 +1,304 @@ + + + + + + 4.0.0 + + org.apache + apache + 3 + ../asf/pom.xml + + org.apache.maven + maven-parent + 4 + pom + Apache Maven + + Maven is a software project management and comprehension tool. Based on the concept of a project object model + (POM), Maven can manage a project's build, reporting and documentation from a central piece of information. + + http://maven.apache.org/ + + jira + http://jira.codehaus.org/browse/MPA + + + continuum + http://maven.zones.apache.org:8080/continuum + + + mail + +
notifications@maven.apache.org
+
+
+
+
+ 2002 + + + Maven Announcements List + announce@maven.apache.org + announce-subscribe@maven.apache.org + announce-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-announce/ + + + Maven Issues List + issues@maven.apache.org + issues-subscribe@maven.apache.org + issues-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-issues/ + + + Maven Notifications List + notifications@maven.apache.org + notifications-subscribe@maven.apache.org + notifications-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-notifications/ + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + ASF + + PMC Chair + + -5 + + + brett + Brett Porter + brett@apache.org + ASF + + PMC Member + + +10 + + + evenisse + Emmanuel Venisse + evenisse@apache.org + ASF + + PMC Member + + +1 + + + kenney + Kenney Westerhof + kenney@apache.org + Neonics + + PMC Member + + + + snicoll + Stephane Nicoll + snicoll@apache.org + ASF + + PMC Member + + +1 + + + vmassol + Vincent Massol + vmassol@apache.org + ASF + + PMC Member + + +1 + + + fgiust + Fabrizio Giustina + fgiust@apache.org + openmind + + PMC Member + + +1 + + + epunzalan + Edwin Punzalan + epunzalan@mergere.com + Mergere + + Committer + + +8 + + + mperham + Mike Perham + mperham@gmail.com + IBM + + PMC Member + + -6 + + + jdcasey + John Casey + jdcasey@apache.org + ASF + + PMC Member + + -5 + + + trygvis + Trygve Laugstol + trygvis@apache.org + ASF + + PMC Member + + +1 + + + vsiveton + Vincent Siveton + vsiveton@apache.org + ASF + + PMC Member + + -5 + + + carlos + Carlos Sanchez + carlos@apache.org + ASF + + PMC Member + + +1 + + + dennisl + Dennis Lundberg + dennisl@apache.org + ASF + + PMC Member + + +1 + + + + + + apache.website + scp://people.apache.org/www/maven.apache.org + + + + + + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven_checks.xml + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven-header.txt + + + + org.apache.maven.plugins + maven-pmd-plugin + + + org.codehaus.mojo + cobertura-maven-plugin + + + org.codehaus.mojo + taglist-maven-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + + + scm:svn:http://svn.apache.org/repos/asf/maven/pom/maven/tags/maven-parent-4 + scm:svn:https://svn.apache.org/repos/asf/maven/pom/maven/tags/maven-parent-4 + http://svn.apache.org/viewvc/maven/pom/maven/tags/maven-parent-4 + +
+ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.md5 new file mode 100644 index 000000000000..9c417645ed8d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.md5 @@ -0,0 +1 @@ +2a4e926f3a76c6e74b0b126f513ad4e7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.sha1 new file mode 100644 index 000000000000..b6caacf5e416 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/4/maven-parent-4.pom.sha1 @@ -0,0 +1 @@ +0fc039b0bd4d17d7c147a30e1d83994629c5297c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom new file mode 100644 index 000000000000..a512366b97f9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom @@ -0,0 +1,466 @@ + + + + + + 4.0.0 + + org.apache + apache + 3 + ../asf/pom.xml + + org.apache.maven + maven-parent + 5 + pom + Apache Maven + + Maven is a software project management and comprehension tool. Based on the concept of a project object model + (POM), Maven can manage a project's build, reporting and documentation from a central piece of information. + + http://maven.apache.org/ + + jira + http://jira.codehaus.org/browse/MPA + + + continuum + http://maven.zones.apache.org/continuum + + + mail + +
notifications@maven.apache.org
+
+
+
+
+ 2002 + + + Maven Announcements List + announce@maven.apache.org + announce-subscribe@maven.apache.org + announce-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-announce/ + + + Maven Issues List + issues@maven.apache.org + issues-subscribe@maven.apache.org + issues-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-issues/ + + + Maven Notifications List + notifications@maven.apache.org + notifications-subscribe@maven.apache.org + notifications-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-notifications/ + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + ASF + + PMC Chair + + -5 + + + brett + Brett Porter + brett@apache.org + ASF + + PMC Member + + +10 + + + evenisse + Emmanuel Venisse + evenisse@apache.org + ASF + + PMC Member + + +1 + + + kenney + Kenney Westerhof + kenney@apache.org + Neonics + + PMC Member + + +1 + + + snicoll + Stephane Nicoll + snicoll@apache.org + ASF + + PMC Member + + +1 + + + vmassol + Vincent Massol + vmassol@apache.org + ASF + + PMC Member + + +1 + + + fgiust + Fabrizio Giustina + fgiust@apache.org + openmind + + PMC Member + + +1 + + + epunzalan + Edwin Punzalan + epunzalan@mergere.com + Mergere + + Committer + + +8 + + + mperham + Mike Perham + mperham@gmail.com + IBM + + PMC Member + + -6 + + + jdcasey + John Casey + jdcasey@apache.org + ASF + + PMC Member + + -5 + + + trygvis + Trygve Laugstol + trygvis@apache.org + ASF + + PMC Member + + +1 + + + vsiveton + Vincent Siveton + vsiveton@apache.org + ASF + + PMC Member + + -5 + + + carlos + Carlos Sanchez + carlos@apache.org + ASF + + PMC Member + + +1 + + + dennisl + Dennis Lundberg + dennisl@apache.org + ASF + + PMC Member + + +1 + + + aheritier + Arnaud Heritier + aheritier@apache.org + ASF + + PMC Member + + +1 + + + handyande + Andrew Williams + handyande@apache.org + + Committer + + 0 + + + jtolentino + Ernesto Tolentino Jr. + jtolentino@apache.org + ASF + + PMC Member + + +8 + + + joakime + Joakim Erdfelt + joakime@apache.org + ASF + + PMC Member + + -5 + + + jmcconnell + Jesse McConnell + jmcconnell@apache.org + ASF + + PMC Member + + -6 + + + wsmoak + Wendy Smoak + wsmoak@apache.org + + Committer + + -7 + + + + + + + apache.website + scp://people.apache.org/www/maven.apache.org + + + + + + + + org.apache.maven.plugins + maven-release-plugin + 2.0-beta-4 + + + https://svn.apache.org/repos/asf/maven/pom/tags + false + deploy + -Prelease + + + + + + + + + ci + + + + org.apache.maven.plugins + maven-pmd-plugin + + + + cpd-check + + + + + + + + + reporting + + + + org.apache.maven.plugins + maven-surefire-report-plugin + + + org.apache.maven.plugins + maven-checkstyle-plugin + + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven_checks.xml + http://svn.apache.org/repos/asf/maven/plugins/trunk/maven-checkstyle-plugin/src/main/resources/config/maven-header.txt + + + + org.apache.maven.plugins + maven-pmd-plugin + + + org.codehaus.mojo + cobertura-maven-plugin + + + org.codehaus.mojo + taglist-maven-plugin + + + org.apache.maven.plugins + maven-jxr-plugin + + + org.apache.maven.plugins + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + + + release + + + + + maven-gpg-plugin + 1.0-alpha-1 + + ${gpg.passphrase} + + + + + sign + + + + + + + true + maven-deploy-plugin + 2.3 + + ${deploy.altRepository} + true + + + + + maven-remote-resources-plugin + 1.0-alpha-1 + + + + process + + + + org.apache:apache-jar-resource-bundle:1.0 + + + + + + + org.apache.maven.plugins + maven-source-plugin + 2.0.2 + + + attach-sources + + jar + + + + + + org.apache.maven.plugins + maven-javadoc-plugin + 2.2 + + + attach-javadocs + + jar + + + + + + + + + + + scm:svn:https://svn.apache.org/repos/asf/maven/pom/tags/maven-parent-5 + scm:svn:https://svn.apache.org/repos/asf/maven/pom/tags/maven-parent-5 + https://svn.apache.org/repos/asf/maven/pom/tags/maven-parent-5 + +
+ diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.md5 new file mode 100644 index 000000000000..27ba3aaf45d9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.md5 @@ -0,0 +1 @@ +4da85635ce64dbec5b00232d5bb26453 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.sha1 new file mode 100644 index 000000000000..5d7a3eba5ad1 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/maven-parent/5/maven-parent-5.pom.sha1 @@ -0,0 +1 @@ +5c1ab38decaca1ccd08294aeab135047ebbae00d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar new file mode 100644 index 0000000000000000000000000000000000000000..79fcf22652b3ae6f771b7e85b0049199229cddc7 GIT binary patch literal 46326 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 literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.md5 new file mode 100644 index 000000000000..60aecbcd2f5e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.md5 @@ -0,0 +1 @@ +f41eb4e07a725eea3332743a29057855 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.sha1 new file mode 100644 index 000000000000..e3f05109919a --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.jar.sha1 @@ -0,0 +1 @@ +abd1c9ace6e87c94a4b91f5176aeb09d954b23a3 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom new file mode 100644 index 000000000000..dca027b28347 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom @@ -0,0 +1,21 @@ + + + wagon + org.apache.maven.wagon + 1.0-beta-2 + + 4.0.0 + wagon-provider-api + Maven Wagon API + 1.0-beta-2 + Maven Wagon API that defines the contract between different Wagon implementations + + + org.codehaus.plexus + plexus-utils + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..0f10b3fdc97d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +97f0a0bd0b81520ccccf8736b1fe380c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..56b9559d4b22 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-provider-api/1.0-beta-2/wagon-provider-api-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +8b3013d0754edbeb694831ddf1c5d1a0019ee042 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom new file mode 100644 index 000000000000..768e3e958d72 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom @@ -0,0 +1,51 @@ + + + + wagon + org.apache.maven.wagon + 1.0-beta-2 + + 4.0.0 + wagon-providers + pom + Maven Wagon Providers Parent + + wagon-file + wagon-ftp + wagon-http-lightweight + wagon-http + wagon-http-shared + wagon-ssh-external + wagon-ssh-common + wagon-ssh-common-test + wagon-ssh + wagon-ssh-ganymed + wagon-webdav + + + + + org.apache.maven.wagon + wagon-ssh-common + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-ssh-common-test + 1.0-beta-2 + test + + + + + + org.apache.maven.wagon + wagon-provider-test + test + + + org.apache.maven.wagon + wagon-provider-api + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..45931fe876e3 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +5690a1f456b3360fe06aa4c81ceead2a \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..e7f68f27d701 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-providers/1.0-beta-2/wagon-providers-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +a98eefeb315d771555c8529695630d3baefd1f6d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.jar new file mode 100644 index 0000000000000000000000000000000000000000..7ef31a349b10169abb087fda79e69ed56facafe2 GIT binary patch literal 17297 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 + + wagon-providers + org.apache.maven.wagon + 1.0-beta-2 + + 4.0.0 + wagon-webdav + Maven Wagon WebDav Provider + 1.0-beta-2 + Wagon that gets and puts artifacts through webdav protocol + + + Henry Isidro + hisidro@exist.com + + + Joakim Erdfelt + joakim@erdfelt.com + + + + + slide + slide-webdavlib + 2.1 + + + commons-logging + commons-logging + 1.0.4 + runtime + + + it.could + webdav + 0.4 + test + + + org.mortbay.jetty + jetty + 4.2.12 + test + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..7b1262e408bf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +fba1e35dd302eba826861b5be7351c4b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..39af910fccdf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon-webdav/1.0-beta-2/wagon-webdav-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +1f6d30fd6d75cba5b9ff3fb88cb35cf9f2895736 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom new file mode 100644 index 000000000000..ca84acc39de4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom @@ -0,0 +1,170 @@ + + + 4.0.0 + + maven-parent + org.apache.maven + 4 + ../pom/maven/pom.xml + + org.apache.maven.wagon + wagon + pom + Maven Wagon + 1.0-beta-2 + Tools to manage artifacts and deployment + http://maven.apache.org/wagon + + + jira + http://jira.codehaus.org/browse/WAGON + + 2003 + + + Maven Wagon User List + wagon-users-subscribe@maven.apache.org + wagon-users-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-wagon-users/ + + + Maven Wagon Developer List + wagon-dev-subscribe@maven.apache.org + wagon-dev-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-wagon-dev/ + + + Maven Commits List + wagon-commits-subscribe@maven.apache.org + wagon-commits-unsubscribe@maven.apache.org + http://mail-archives.apache.org/mod_mbox/maven-wagon-commits/ + + + + + michal + Michal Maczka + michal@codehaus.org + Codehaus + + Developer + + + + + scm:svn:https://svn.apache.org/repos/asf/maven/wagon/tags/wagon-1.0-beta-2 + scm:svn:https://svn.apache.org/repos/asf/maven/wagon/tags/wagon-1.0-beta-2 + https://svn.apache.org/repos/asf/maven/wagon/tags/wagon-1.0-beta-2 + + + + + + maven-release-plugin + + https://svn.apache.org/repos/asf/maven/wagon/tags + + + + + + + wagon-provider-api + wagon-provider-test + wagon-providers + + + + junit + junit + test + + + + + + org.apache.maven.wagon + wagon-provider-api + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-provider-test + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-ssh-common-test + 1.0-beta-2 + + + org.apache.maven.wagon + wagon-ssh-common + 1.0-beta-2 + + + junit + junit + 4.13.1 + + + org.codehaus.plexus + plexus-interactivity-api + 1.0-alpha-4 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-8 + + + org.codehaus.plexus + plexus-utils + 1.0.4 + + + + + + + sharedResources + + + people.apache.org + http://people.apache.org/repo/m2-snapshot-repository + + true + + + + + + + org.apache.maven.plugins + maven-remote-resources-plugin + 1.0-alpha-1 + + + + process + + + + org.apache:apache-jar-resource-bundle:1.0 + + + + + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 new file mode 100644 index 000000000000..45e066d7355f --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.md5 @@ -0,0 +1 @@ +e739bffedc84a18c6e10a0958e2006ad \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.sha1 new file mode 100644 index 000000000000..5f82f766bd1e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/apache/maven/wagon/wagon/1.0-beta-2/wagon-1.0-beta-2.pom.sha1 @@ -0,0 +1 @@ +6cf8a47018be792d2b1774d2bacd7541c888ae50 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.jar new file mode 100644 index 0000000000000000000000000000000000000000..d3232758f2e13c9bde24a1e99da866722000a0e5 GIT binary patch literal 15961 zcmb`u1yo(h7A;C}cXxM4aCdh{7W42!g? zbufMT+56>%`sZOX02KBU3#m zhyTOS@7w$i_Qz0LOC#66%-H{lp70-L7}!`^8W}j6*;xPJgZyRja^1cby{~|Ps6l{$ z82`m=ffp2KBWW`SM^XlQ14}&zhe*XG>uG*Op2K`+3s|#hm;@=bFc^uZCT<9#96>Tt z1AIl5O}j1Y%!=g|^W%gwRqj{7P^)*8z4P$)D#X5k#f4N32jj7MJ|C~gC~*9|Q+<#* zyk*N^(kw>7-T2E2pc>XfAidpTu9GNdXPpTQO!kcMbY z)S%>UIS>>p<8-Tv@!!zG@fCa0+G8=zqmlK<-T>RD;FQD(*vQ&BL~}CL3zi5obKpTa zd=#S+SKjrtpzx^OECpG`a>$>TR5get{F5$&y>DeuJpi~+M<{oyD4H0CMfNkEqxFtph&|3d2JT!H2p<5Rav3~* zIcIUvxdbI<+ngknl6`oDUh~PVv!kF&{`yn~>{tye5+9jUnbV1`<<*0Es5S8g8}YEK z;F!h-HXDhrOeKa-8G2r;F5HHD&z-1_x;+9!Cb474>KG|^s_R|dDi_4}EOfQUPZ-tF z8*I$0Jl_I#OlZFml1}sjf1%UL`=Bk#I+^R?ug_XTYfuo;xL+Pu;m%ww`XTT-b&ZON z6wzg`;TGq2gZ|YfmLb5G9D#v=lEHw0-uzEC@tZ{?XxhA3MBq3%ku2?W{XW=KQY(xz zl^x8NG(S`kFcINMVQSL#LA#`x3Inl5rGm~7li~nGgf`;yJVXO~hht@Pe8#UI9LB~@ zj_$|T-gn0Ig0zhY_PT@Lh=kz~$Lgb-nF6zdSwgu|uE)N!0)Hc}vb1B}H^md}0bAm7 zy+|+A;ap5`m{zc4Rk6`pxI)jc9RXsEdk*NU@mi^;@=$>K@;N^RG<1(WMwVhLA2H)T0ylccL(5$s{q5AEAZ@@UU)FA)#xHu8=Uz?;^mEobL55do$Re@D;s*RX1b?+)buR6(=NHQjc~Q3S z2h888=$|$5S5*`GLnVK;W2@*c*=~Nspl4sf2Flz?mv{b^E^Foq##A$$oh)Rz`xYk;*;U81U4=*u zJ4A&W>&(S7H507i(r<+avQ3{wsPnTfiK!~yVA=3&6B+fbadxkpoD|I!s6s_Q zKi9Hy?kr*sgy^X-}D7-FZ4sLG&6@>Y`59-YX`pyJmB`t?yW1!V{w?>ut z%6zx?GI{H?#OK4rGw@$;=~s%9<6LkcAUYHvAohQAOZ6Qb?ez>Ce;gRU-qZ@fohphd z>Jxq_79Sqe8XwaCUe9+rGHLzAFgzNzVStda4Ou*-+ znTX+(jaqduRqS&?)X1ix=(iDZXJlZnXtT1ki zbU|$^Tjv2grMZ1aWT{y=Hj%|yr9Bl_m^4n_kGnKr@_?B(1z4SoXtQRrlvQ_TO>Jbn zuLn?*!xZug4Kvih-kLj7=xZ#{c2-Nc`@TnZWhAR_dg3LqVSm69Jg^>!5{DAO!&pjy+M+A6g$%NdsDt@KwpbUaNduE+Y${Gy0l zp+b)>r@Q($j2Wil!-klEUK&|3it+gNj>>6a>AE_u9kI_`MtczmQuIiqIL@z6@{1AO zJIxr&FJKdJd!*q(@u5gEFGzwucYrNakeMmXQSu>aj;kkAhKy`_!@3MM(KB3Nc?D5- zsh}t9Wr~Tm1&6itRI41s!d8*-R2045OYLdtiRVWOb5W7MMn=KQkT?X3^nPw{tQ{0~RcmzJ>%=?ASB)r_TRAFDT@YmqE zS}GLcux5KP_U?mokxuO9Pe9B`cZ_&BRq}F5UTgAvsr@qMHjmcSA@s_)UhB%JY}J!0 zjMcmXnUVQH0f|hcE_OU9cOLY%uS=^d6|HDyE^OlztzRzDd<-T@@ycM?6tsKCku3g` zW2&Dz7G~esnxOiLnBxfbf|=LAdPR->hUdzdL7qMjYq2XLLW!Dx12u1VKQ(Wc2H5-3 zTiEwyYQdN)1{^yS7k!F3x(iWRSah~gGerVDjE>24y%D%7R#A%@lxPNN75x`UD8q@k zI)_Wm*Fx60#i}4xHR@VNn!3qER9QJizLv|>pz-u%W*L}Jxxq8v`*;vz1TknhPm{iLJvvpK zuEGYHp3e?bs47f@dd2<7a5XdgR$kJvYO+QPswb##a1w$mPcBKEgNQ+i2%n8eIzfhY3Bmo`Z!3of>jD+j>JL3Hvv`zM+>S=Jp2t|L z;)4!9b9RpO8ph+ybVV)LT=y7_myz3Km+2La(YPN zCaevZE;N0{pA9KZ$N|J!nMh7~yS7h=mrx_k+ZO5+s@p+*F{?kc*Q%IJF`#%^WVjcv zzVXA#Cq`@Eq$SfL*|+$)vZqZ%@;x&vQatI$^&n%hhH*zG13IiBiUHpa`vvSMHW<`{ zUJX@Q@L@@l*D4ud*x$5Hri}HGi=%?4Q8(SZc#MwD{9WYFR!4M5@sxWsWO+l%H|$pX@f#) zo+L|wh2yR}oY>vmyU7sVprZY9Es*}ZnwV&bFI((HiSK)vShkDuFQ77#hQ`;`OTIN@ z-;Ylp#SD%so(^sA7B3pwN17{>%f)AawZb}<%%TnsYp92rxv|N_mMmwM&SRmDUYu~> z>8xraPWP{+>aX6n;)>+84UaFW>!&3(N8E8~z~l#eJ{Wv?IBI`+V*NL+ zgs_pZo|ENo$DWdrn5)%$>QEG*l%+S0oex zd`=NhyL>_)5@lR8>2B}0LY;ax+dUBr)?}XMftt zO$;=O^Sm$*HMF{iZe^HTC>A|@NF|J&oHrKT+{lGQ-@F0UmDwfhHGXhla+nt`bp6mL z42IzabU|99D;u!WGQ%4T`8S6MP<$02I*H9Bm_FDDY^p=Ii6TaFf}`F5{Eu@`7nSS&%a zo`uw;+w6j)q`kk6k_V7=eIz+S&_qnZkz3AOn99P&@WOJbp zt|tn}yBgi9^^O!Iiwt}T+H>9PArbf-wt=sFWGSL7Cpf2uG%)?aGP2*Bp-wlwIpc@~wq*rohRQ@kk{VWBCA!34 z&>O;%R!GR!+Vc=aWq1I78)S&Kdxqu)b8#2495MhMOE&K?pfo@Pkf@gQQyDlsM3nN2 zt}d%bKMyQ$8KCp|C=BjHy61`6h^W8&U=7vy&gRTYjlPAQME8!_(hk%TDOm_p`y-?? z%|RfwEr^(tcc^Jzo*M{3G1LRiJ~_3>yD1uV%T+8+4+ zDh^{$b9;L)Pst4kKtOE&vs3(sI#d82R8hoGpU6WO5d8?j${Wl*h4{D1Dnu+qpe5mQ z{pwB2wByKVNf#XJ1Zqxi9v-9Tv#5jJWtZMRh+SW$4;rIvif&{))iOEkuAX+B9{u7E z`>_YS&7F@*r*j4Wu)SLWu=HQ`GhtW?V`hvqHcbg9#1R3#RLGKngTY46Gwm6Lw6`A} zmdimy52JI%X$*=3wa?uXh$WD;*iV=!{~MX@%8>BP3VJZXa($EcfwCOr}O!4qtot}C9Z zkL*q^9c-F|1o7xNy^x~^712}<=|qu(&thKb-m;IMree3yX(_=Z8Pk4eH14C_TNN{! zWTvSoGc?J;oP{`pLo<_*T{43y+hVtB7j1eTY)mr~`Ef(g7LP+~3S*4o6Xi9h#e$^; z5)1!>)hRtm_%HUrOIjPX20L**SvAnv{m+uRN}MKp5!Ump7qiGhgtR*)_VUHcQav;e zofk8nP72 zhY3b>N#P`)Ve}gdb|bHHV>wO_BHfdvD?}|SOQDZT)9M;U8x#}uWEc+=Ka-cuH*FwWt4ALG*^u%q*f_-O==uPxX<@coZj?p8 zSKxM!)#GxjbAJIMCeUXO$M@+B#T$LTHOiOD*0E<=EjzD93+z4%QVE4XP0VFhq`n6y zV#{4X_40h8WhZZV3>->3Q#_KHVM;Z~YTpd6!SeMAFvTPI9A|KY4lOoVhcHM7=2M_h zbBKWoC9p?UdC0izrxdz)j*Yy+C`J|=%@0Ow#dfpDH$gRtnxdax%Z)Cl;ikqRcx|De zR3z9B(K0YUq_uuYvX&TP_L3}0pRp7&vt>6j!ooZA7$+bLbiTZ?-~#m-_k$cz0I~hD ztUzM|JBJ53XeV6x$c?v4-DE9U&i}1+9{vpH3$$S1fOkx*S|C*W-WK&MWcqg^Dgu?Q zWc<0$yuhKp50K>dsz}JUaOnUf_;ucTY*z$d{&d0m;y_j_a;*$>JY{9D9qKqPvvzr| zeYtlJ-mpzWh-}-dHCCJo7LoWj(yh zTz5aU%^J1-gKmw!O@u9QZjYQ$77DHLtfhA*Meo-aE^$6$yVC+Nj(PX>$=Vkm@D|&_ zQxx8}9Cn9eItE(J#RzY{(l{+3?G>sYE!TB0c>r-d!`;3B(o_q{6hPlpxPR|D=z{m-F!zt|Hze$oCt;FjOv$vbGj#W1I((X zCvDrUrP#gG<(9A_kXxLk`IX3G7}I`zJoDh-MPDRi1=px7iYKs$yM66jkXz?9aR8xU2EkR~)E9brg9yo5wfN1y-58~hq(9a~ZI>v;)Kk-vDC4FBfv_$BoI za%lW1@-DmdJ@O9vx`{s7_86`}m+)1C^?QG6B8_~>k_W_qnf^$1T#~x*S@?j?&5{a@ z60cJ+6}%;1LhO>yl3ZL&CiJ`Wo!&kVzR)_lOI^rG8~}EF4%Y|@_`vt}<@VerXFbCC zB}FpZf%j@(h54?>P&f!t4oGA5&@B?(Jq%wPiW$Q?94pxoeG@JoSQ`)5gjLF>G=f^<(YVMYXJdXl=ncM0AaUkd!Mv4j5}1bqmM@~^!Szu6Cf7D zkCFZ1A|Dhh4=#9DA0(Z=abn$+@hE2EDRRP_s@_M;^w}9J+SISht15w6#3Ge(BnsU7 zC`%D(-`Pe6+&fo>a4cl$8>P!U(|v8iM5y6cfx?oI0d-U6ehI_VPt;?pZ)l?)!o*-l zpN;)EEp4|g$@isWo!;d<1JToRlfKSgnYM&UCB&5&@0A*I3Pdbtn>ayMfhC{u<%MNStZw!g)< z2s{hR7PbjIi|Jk0V!WboF0%_3^(e~e$W{&oS6e|Izq2#u&{NHsT%UrF z#4%W0n`%bFn!tnbt$Y9Di0(<&Lv9fWnE?n6DO+E8Fp-dx@W~n}Ma;%Zu}*Woo^F+Nh*F%nv5%|9 zu6%2)OG=93qa>3`cKq?J>-udZ%-<%RluD+(ZECq;m*vo>$z?ps%@A0QmBF1$A*4#& z;2YCEr4p3BDd(#5I36QPC?W*UBf09BDv91L||K_!0S)xfSeOn3n8 zB$ZgB;D8LR91)FLrl9r4S6D?E64ZV8lc_aqqADu;iwZA@2Y-9AOOyqx}l25>iL&VTL;|BtpsWPof#K8fm0# zQASA}b}}wAhi@8w$@={wKG68K+}mnSXOPi&(0m(eTdtqhgG0rY$g~M64%nSPG z4OR;YKKKNDmCAY46ntPCb`?f}J%K35r_vZs(DUX#Gq{Ne6aTkorOK^u`oxAZqvuaz!X#r7R1OmH&BIo2 zgV*iVV-otp;#ZdWqOWYqQ7*iB_h3qVkWk7DB5p8sSB>EV)H{1RIVm#QJ2mpc7LMqH zNlesgxl7#_163GUo54j_X-{x}eU?#{%ZQ|Y5g)DpNqk;R;y3Y8mieCa^Gg3NK7~+J z_3|An`br_1dlisSBCm3S0K~<}%eXFyEl#sZ?UiY7d$FjAdVOh-`JfrbRAn-Ryv|(L z#yps~m=5`Te4YgH$E%fs!XU`Fl?Qnha}3%eh*?p&0lJiL(6|+<2Z6wkGZDEh-JMa- zLvqeGvRCwr8|03dmM$zO>o^%5MQoD!cT>2Ez7_Aon6(lwZh-_Dk$iEV;Ms^;X5nKh zu5bv3n7S6pU#AlC3i34dU@$3;*hq@m$nGH%`us*Ltj3WioG`3Bs(qCl9_NzSm?$Wa zA^ZZDT5h&y!f`h7nV7|EoCKdtdS*(h-yx9ZEyFh4Wz50URdk%=Qsw%CUFUF5wDTN^ z@bRtP-Wi*9t(vC{u*tV}JZ5CQNcTzIH;>hGwjn;2{R$*!w;Wg|*!1So>e#fFRP(cE zxUZRMb?tf^$t^8<8x<`rhK$wHDu8=tKkp?M6>(~#8x^;>eSy8Q3TnSwef)@_B~G*L zOVB)p0D=Bq8uGJu+sfC+Y4(&Tc>gb?@g?zvypuCxY3|e@JSzU?=BPmiGRL%0%9yi} zN4n__kcn6!0{eE&Ha8`MPCX-Gs8o=s+wy{`)}PI%xPT;m>#K#u69HhgEP|CLF`P*z zF*r>e{^f?A06UsU`J*MZyeh7MBYFD4y00&pI_idHgl#_UcU}UqF{hMT>x-(SKJQwu z=;Oflzt~1w!r$b?sz9ljAy7Vo{4l%k=zP;i-M#SD5& zW+sgn990h1So6x?Spuf%sjy9%guIg%)mfb(d$jCGcO)*!jwPF~G8#SQ%F*M(VeejL>ose~@iR`7}>J({o9t*k$eD5q$~}J)A8IWo$> zJKL5qAE)nNuNBRL0KieK*STr+9VOu0yxNt;J`XDH|Ja}MS)T0-wKJqk1O$$I`mD@% z_;%`Jn`wvOBtKL*c#`dC_L6uH&Ko$|twP_mvk1LAq0?7AqY_jWqi>*TJ(!D_8Fne1 zh0vBZ1ok|V4u#vh5)RweoyVP<7tAz?*!r-}dy1t5s_v7$1Vro~0pYYZv)=%pQS4e_ zHO<`~@YYCf(q5h3=AhgOjBkVZOq_1pkKWw0Waiin;8C2=G$%=SSRKdbFX&4+J=CHi zV)%RuyIRZqRuf9nY1zx+xLUNIDZNFKA@GWj>CFbb`L3yBy1VG(%qC8C=N?I5-ORy^ zKQbe#dsIh+H{#e9$^qEA5>zn~Cmkbta%H>d0o)V?)$SV^H$VFl0xGJ_Lnf_|K~CO& z3{<)S3^F&RI2K}>YK)kIe3Ek3UUQ*xQKV#j+GZVnRWsTPhw!Rcb@%WR)F;f`I=jU$ zm>!J;ti3z7V5(ckX#_CC@i z@c*lD+aF@_dkUKTB?a9>ETW~sLf=PP9NRME*FX%`0Gi`hKOsU9FNT>qB29rp>Rj{C zaYInUqk`~92Ksfp1SWZ6*7VzpofVf;mrj=t$(>J6$1cKluzY0IICsuRexH1x@#djs zqj=N~_>qRS3Wu9M2PJ|o>XMqijnf;dM&1+dfMb2Tw#g?8F=V@>&_ylQyb{y^uWTpw zX^C+)_PjFU#&9|DydxmR083iX<|L`5)EMqFt+9!=7+W|A@*>Nyqsoe5R6vnKlG2Dd zz?ZHp(SDY79-EFyAFHe^R%W?6OvKujedgUu0-BZLB>~N`GP81toLh3mJ&8pE0=2^7 z*Q!DFC6%dY#{!g2hGj=ZY}Z2$(;@k~HXuHyl6m+|%FaQO`dHM?aAltP3FWcsLV|hx z?#4_~Wj)86j9u1IUFsD^b5$)U6D1jq={wDBXTv(uc6DJ@`OMAG$n!N@R$(Gyg1jIB z$*lCSG8}bpsIh!5LK3gw#Bvqrael}OdE`knK!GDhYWig@Ta2U)gO8!GHJPPc0UJYX zNUw7Ec7o-wVPU#cidCZ1oPDW!VvKjPbm_)}TQpWhkp!AsbIi;V`dMnVh>oec?ZiXdQir~D3xyB=J>r1mq~VUEa29u zT`6TJ!&JYy5g8-y*j&kuyc^jp(|N<$5V_1*Z@e3-Ubbm!DY%Qg*p3J=3C`6?jSPhr)W6g4{(6TzM&~(o4ZF8>cG4h$BKNS zh&VFh7DEn+Ct+A6)EA|J?&t->dP{YSy*6+Q=yG8%S@-z%aW^5Gd`k>0oSklC0)3|} zAm^F8jqD2aP+IW5<_+AXlwM0hb*+)&T&qgw{uNoFirI|Gu~EawK_rc+&@mXct8`UV z_zt}|drP42L_z_+54v1QA+_j54PB(6TxKW!T%p4j-6pcR5ZsYRW;JeS0Pv}%7r^@5 zOWrCyl^ZArbE8k(*{V_{UYz~bRqTooL#;z_C>4=SCa&42zhzX3n0zm)+D@V;&&$)? z*m~pB%pR=QT$;elXwIyQsr$9yFmKGk{Hy!t#`LG#f~QaqU>Z@=u-%em=Z_+B zZQ?o<;?8{(1Vx0=>lxL9w@>?BxlAX|<&caMB3Z=COPu$_kgNJF`{>&ELvCGy#QV-| z?_h|!LcsNQ1pOH#XAadvLv(xH2F3g%>-bs2Wz<6-)I-Cm3!lX?^ALrKx)2~{6@kg z^3BdI!(fpui!!gwXB_hPW;xG{m4QPhnghGGJj%Rs_JeEfeyTzZ=;Esr8mO6owRTZh zoYpzEqt$FmW@j7Z51&p%4a5#*kPNQ>^c4Kv_be*XmxXvaPY@9QUHaxPx!vzIu)igD zlVn_$gi(XmLgOiGL?q)`CkhjQAFDGPt<$_?IIS4WG?vryV-yL$-7Y|;h@{XTP~uYe*^MH4fZfvh|N>Tp!YOkZn?b8^f0O1S$lqZf}qOiVKc++ z?qPljjxRrCjOv3&pMj;nUhwSOv0#l}z_d)7Pq9o|5ND;aEVTrr>YJ%ep9%X{=xGbd zWcw_Zsz1T`Dzo0mXS;k-PXdOZ2FQ%D%qHhQd{nD7Gi=&S33{BcrSpb|@OV@iMoB4W zw{Fm#8d1sHKs#t$&i~|SshQUCWu~p0u34YivQs!3r&iz1TS1q)EW?@4)Hox}CI%F0>3qiyyu*&xO1hBOR^UwUlww@`#rj?SH zp<3`1N-^*zB;J=&7N}|Z)(Y7+J=Hk1C@3B1;^Wq7wfMdA{z9^?)nrTP?8tFA9Yz?& ziwX#P`~0ArM!Fd|}2 zc1)=0+xQAC*hdIBK&Wb&v@gR(?QrQ;u{`)H*=rkw3nh5uhgq!b7cT#@t9F?9gV`igkZel{=6BeF}ooqjk^j`6LZ4`o?Nx?u#%_o4x zKqDZ(*=Vs={w)i)`uY|f+aov!j|E_HnmX=SxlGv_8m)*^)1cGH*TdZF(5Z;r!n-Tc zslSf0NE2*ruwgCxI}r{_l4u5 zm4@H33GoL`P-Vpu@IB!2ypCCv;qVi1=3lFd`XkZ199F+ihV4D;h9m$xxd6Pfmwr?%%9d?~sIr_XgHhhO?)zVOdWf+@x z<92YP$R*oZ=h!N5@US)S3H+5Cy0sePO-^@|mC#|=`K6kOjg# z^mdiuy~LFir1y!gxdcaClWf2lf}8T(B;nem9l?qNEjak%JTb18I1q{qkighvLfDlY2x=4te6F2rG*v(nATrHaP7AX}Gev#- zDVLlwtP4T1+jG+om2ADA9wyf!UL$IA{W(8D$fYvCkSgk7Tsuz0g{=X%kLX#1Dwy7z zh{(M@7$xd!)dTmU-)Wq=Q5eW$x+0dgFv>+C`zN0xw+OJ$GGCv!eSY`V|Ff;*#a;i= z)?uaRY-IhXu7{s{KuG>`@JsnF{qIc>^#9QW@iPF=zXSLchwi0B^`)VK?$6c0zi$K* z=<~}Vk*n|3jr0;1tA8ne75;yPwzaXMceS!?SLw1|dIQ_OOA~<$qGmsSgU zou*oUzCzcCT!DPpkCba+EjnqlS0Y}Q$C2%PKh`tfl#{JdC+}>qQE|}=zp9OmX^h5H zf$0q)V8Fa}J9>@amTp*$HELvGc96%TZlQWqX5DL`mg@Q1_SqkoM!diozn=fX-hKzz z^)1Xx;-P_1#2!&(>{$b*LO)>)^L8?9m0NqwQ9+x$M&?4?{jF)A);4^gGpMswIeK)b%y za|FD?sue-bMdg9zXjf!}%qn=jN0fv;-R9tD9p*%@${=%}`>yYdcSJn|fW9qf|(JJwS5skwFpoa0sQS?o^0 zoSK$+xLJPIw5;{aS)djxYk3HWEL#&=Db*xg7l@WL`M1!pw41!X*$Kh1hr=>i7x|6_ zn+xV==hRjR2zv+bM)pMr|JCcH@aSrbJ4$Y?hCF#pJiZmbkEs^d<(dgmtYn!82CG&> z?ET9wD{9TTZU zEZs11Gmr@N5q_xh> zwthuDdk45mJ(~^#syv75`1<&|RH{whO%jSrk$&@~r0x|kD#$S2zW&;|^*iU^_ip`|vGv=G z-<9b_)Bbtt_g=1FukX8re@VUkT~ETF5&o{X>jwh=KOp>7$9`YW-}id`zM_0z?|*^z zqmcji9MF%|{(axj5B#{70Po-J_s^^Sf&Z&l{WJQ{Jsm&Lm0y(k-=Pcr)Zy_n$Ind; zKRAjY{sqTBv^@OG@^eY)50>}v|DEM84}j0simJ>E{gS4{#^Ee+&MneCW?>|2doX13rY{e}Mnb zwf|ktYyH7NL;l}6{%Sz~Nb>Uo_zw~f+W$`SmyP^* z9RIPCzxPCcCHXGHb1!8#f1Db>`=!5Y=6_E9?wS6W4EoY8`_tqX5&9cH^`8O1d#XPG zMgAS&|H*Ito$BvB*WbzVeY5{xsebcgf81)wUwXNJc3gfiqOkm{yY + 4.0.0 + + plexus-components + org.codehaus.plexus + 1.1.6 + + + plexus-active-collections + 1.0-beta-1 + Plexus Container-Backed Active Collections + + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-16 + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-16 + + + junit + junit + 4.13.1 + test + + + + + + + maven-surefire-plugin + + + **/TestComponent.java + **/TestBadComponent.java + **/*TCK.java + + + + + + + + scm:svn:https://svn.codehaus.org/plexus/tags/plexus-active-collections-1.0-beta-1 + scm:svn:https://svn.codehaus.org/plexus/tags/plexus-active-collections-1.0-beta-1 + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.md5 new file mode 100644 index 000000000000..145191263a49 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.md5 @@ -0,0 +1 @@ +d844f3e1934a76cefc25342bf02f3bff \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.sha1 new file mode 100644 index 000000000000..5442cbcd9ea7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-active-collections/1.0-beta-1/plexus-active-collections-1.0-beta-1.pom.sha1 @@ -0,0 +1 @@ +cf6a9d40df4ca79c210b2b8a90ce28fffb202769 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.jar new file mode 100644 index 0000000000000000000000000000000000000000..e2143250f5ffc47fd18860f17a496f42b926fd35 GIT binary patch literal 42472 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�L3Y0YVt(;Jf3OBZcDgMMnfbo8)W`yj z8U`5>zN|8s#t=i_B50f|2y8#jDsW!ZD^wmD)d$L(pI}v<_0b0!iw4rTPAyHF`}WE> zG7Wla(C{V@wkhxzU<`wupe*R_Iml89{sk7py>uuGy1NImzK8w-i@v?Y_=1J*T7i%- z;%`6}>|sGq2)aK3vUnnvW-Z*U0JVSi%W3PlGY8Gp)Qg`_d^HgsI + + + + plexus + org.codehaus.plexus + 1.0.10 + + 4.0.0 + org.codehaus.plexus + plexus-classworlds + jar + Plexus Classworlds + 1.2-alpha-10 + + 2002 + + + junit + junit + 4.13.1 + jar + compile + + + + + + maven-surefire-plugin + + once + + + + maven-compiler-plugin + + + org/codehaus/plexus/classworlds/event/* + + + + + + + + debug + + + aspectj + aspectjrt + 1.5.0 + + + + + + org.codehaus.mojo + aspectj-maven-plugin + + + + compile + + + + + 1.4 + + + + + + + + scm:svn:http://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-10 + scm:svn:https://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-10 + http://fisheye.codehaus.org/browse/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-10 + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.md5 new file mode 100644 index 000000000000..47dbce552644 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.md5 @@ -0,0 +1 @@ +1a7177f5992983aeb393089af67e51dc \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.sha1 new file mode 100644 index 000000000000..eafd9a79fd49 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-10/plexus-classworlds-1.2-alpha-10.pom.sha1 @@ -0,0 +1 @@ +11215912b045533ec9aaba9f63ea27acf6da850e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar new file mode 100644 index 0000000000000000000000000000000000000000..a8f6a7d3ede85c055903242452d3593549b9de33 GIT binary patch literal 42636 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

&9 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 literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.md5 new file mode 100644 index 000000000000..09c3bbade17e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.md5 @@ -0,0 +1 @@ +b00a4521e82cd7cdf502039dd59a1ffb \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.sha1 new file mode 100644 index 000000000000..9a43138c2a1b --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.jar.sha1 @@ -0,0 +1 @@ +ed03d1eeb9b2576747df0d2883d9006fa5e1febe \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom new file mode 100644 index 000000000000..d2fc895a2afb --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom @@ -0,0 +1,78 @@ + + + plexus + org.codehaus.plexus + 1.0.9 + + 4.0.0 + org.codehaus.plexus + plexus-classworlds + Plexus Classworlds + 1.2-alpha-7 + + 2002 + + scm:svn:http://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-7 + scm:svn:https://svn.codehaus.org/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-7 + http://fisheye.codehaus.org/browse/plexus/plexus-classworlds/tags/plexus-classworlds-1.2-alpha-7 + + + + + maven-surefire-plugin + + once + + + + maven-compiler-plugin + + + org/codehaus/plexus/classworlds/event/* + + + + + + + + debug + + + + org.codehaus.mojo + aspectj-maven-plugin + + + + compile + + + + + 1.4 + + + + + + + aspectj + aspectjrt + 1.5.0 + + + + + + + junit + junit + 4.13.1 + compile + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.md5 new file mode 100644 index 000000000000..e9083e7996e5 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.md5 @@ -0,0 +1 @@ +80962d09b250824806ca66b0bd0ad4c1 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.sha1 new file mode 100644 index 000000000000..4b9e8a40b640 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-classworlds/1.2-alpha-7/plexus-classworlds-1.2-alpha-7.pom.sha1 @@ -0,0 +1 @@ +6944ec0d0cab19adf167332f7197e045d64a577c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar new file mode 100644 index 0000000000000000000000000000000000000000..85669fdd858ee2a6f1c697e28f8e65ce60fdca7c GIT binary patch literal 33149 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 literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.md5 new file mode 100644 index 000000000000..1830fc9e9b3a --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.md5 @@ -0,0 +1 @@ +4fe3c03b97ff12905d0fb10fc5b36766 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.sha1 new file mode 100644 index 000000000000..7456120dbd0e --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.jar.sha1 @@ -0,0 +1 @@ +5a2100a1c6a37804b1abfc70000b0ea33b83b7f9 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom new file mode 100644 index 000000000000..b151164086c2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom @@ -0,0 +1,63 @@ + + + plexus-containers + org.codehaus.plexus + 1.0-alpha-16 + + 4.0.0 + plexus-component-api + Plexus Component API + 1.0-alpha-16 + + + + maven-surefire-plugin + 2.2 + + + **/Test*.java + **/Abstract*.java + + + + + + + + org.codehaus.plexus + plexus-classworlds + + + + + + maven-surefire-report-plugin + + + maven-pmd-plugin + + + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.md5 new file mode 100644 index 000000000000..78fc8ace6433 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.md5 @@ -0,0 +1 @@ +751ea77f1e617aea90f36d7156762bf5 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.sha1 new file mode 100644 index 000000000000..dea608840f98 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-16/plexus-component-api-1.0-alpha-16.pom.sha1 @@ -0,0 +1 @@ +53ad54acd9589c497ba54740f0455fec55db64d7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar new file mode 100644 index 0000000000000000000000000000000000000000..5e3a919c470c7a703773f664a39c6d34fa85a5b4 GIT binary patch literal 36108 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 EA2FjpegFUf literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.md5 new file mode 100644 index 000000000000..beb51a4fb8e8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.md5 @@ -0,0 +1 @@ +7146edcc3412c2b54df27edaf66b00a6 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.sha1 new file mode 100644 index 000000000000..4a7df6b7be56 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.jar.sha1 @@ -0,0 +1 @@ +b226de4eb8db939dff4e14eb5aa1be045c39f6f4 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom new file mode 100644 index 000000000000..f6ff7ea05681 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom @@ -0,0 +1,61 @@ + + 4.0.0 + + org.codehaus.plexus + plexus-containers + 1.0-alpha-32 + + plexus-component-api + Plexus Component API + 1.0-alpha-32 + + + + maven-surefire-plugin + 2.2 + + + **/Test*.java + **/Abstract*.java + + + + + + + + org.codehaus.plexus + plexus-classworlds + + + + + + + maven-surefire-report-plugin + + + maven-pmd-plugin + + + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.md5 new file mode 100644 index 000000000000..40890b2c332f --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.md5 @@ -0,0 +1 @@ +a181ee89516009cff7658eec175ccb23 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.sha1 new file mode 100644 index 000000000000..f854c7a1436b --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-component-api/1.0-alpha-32/plexus-component-api-1.0-alpha-32.pom.sha1 @@ -0,0 +1 @@ +e214782e714b87b38d5605cb8da53b7d98efde06 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom new file mode 100644 index 000000000000..2adef07e6e46 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom @@ -0,0 +1,60 @@ + + + + 4.0.0 + + plexus + org.codehaus.plexus + 1.0.8 + + org.codehaus.plexus + plexus-components + pom + 1.1.6 + Plexus Components Parent Project + + + + org.codehaus.plexus + plexus-container-default + 1.0-alpha-8 + + + + plexus-action + plexus-archiver + plexus-bayesian + plexus-command + plexus-compiler + plexus-drools + plexus-formica + plexus-formica-web + plexus-hibernate + plexus-i18n + plexus-interactivity + plexus-ircbot + plexus-jdo + plexus-jetty-httpd + plexus-jetty + plexus-mimetyper + plexus-notification + plexus-resource + plexus-security + plexus-summit + plexus-taskqueue + plexus-velocity + plexus-xmlrpc + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.md5 new file mode 100644 index 000000000000..cf57067b0dd8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.md5 @@ -0,0 +1 @@ +b76cb94eb4ade475f4743d3656c40899 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.sha1 new file mode 100644 index 000000000000..b9f0aa795324 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-components/1.1.6/plexus-components-1.1.6.pom.sha1 @@ -0,0 +1 @@ +682713aa402653d0ea5e224870dc899803734519 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar new file mode 100644 index 0000000000000000000000000000000000000000..ef2bd9072a34d8e97d0df68fe6bd474e14273707 GIT binary patch literal 210679 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 z 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

UZh^skc#burH9*OFBMzsE= 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�F*uRs~)wt<`*?rWQSc*7 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 literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.md5 new file mode 100644 index 000000000000..fc1ee0b6f3c6 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.md5 @@ -0,0 +1 @@ +00b4ce443fa584a1998cd6f991ea6514 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.sha1 new file mode 100644 index 000000000000..879c8890a4f7 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.jar.sha1 @@ -0,0 +1 @@ +dcad8d44306c5ecc109b9449f292fb28b75d37ef \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom new file mode 100644 index 000000000000..f5ae54892c72 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom @@ -0,0 +1,56 @@ + + + plexus-containers + org.codehaus.plexus + 1.0-alpha-16 + + 4.0.0 + plexus-container-default + Default Plexus Container + 1.0-alpha-16 + + + + maven-surefire-plugin + + once + + **/Test*.java + **/Abstract*.java + + + + + maven-assembly-plugin + + + jar-with-dependencies + + + + + + + + org.codehaus.plexus + plexus-component-api + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-classworlds + + + jmock + jmock + 1.0.1 + test + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.md5 new file mode 100644 index 000000000000..611807a8bdd4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.md5 @@ -0,0 +1 @@ +883b6e1e40cccb06c1d1ce93728b0a9d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.sha1 new file mode 100644 index 000000000000..ea4d6dc0032d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-16/plexus-container-default-1.0-alpha-16.pom.sha1 @@ -0,0 +1 @@ +435f5d09ea241e93acaecd4b6680ddb13a36837d \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar new file mode 100644 index 0000000000000000000000000000000000000000..308893f6247316db7ce5d64d97e939e4bcc5d0d9 GIT binary patch literal 238880 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

%*oy{p*-?iO*8=sLUu# za=JU1?cz_5)u}Ghibymf*XtMM<-nZ}CtSno{nbdK1|o(}j}=M%r#;K1UOje(B$_9n z(>0XbP70-48rF3>ToK$1cSL4pPh2AEXpd+~=Ysp~6hbcc74q$_9L?a$*$$!v)3A9z zLj;M$#;IVbl)7PH%xvfH5rR3($^1WWqN@L<1gq%eU~Xe7=xkzQ{J-^peCA9P(rLGr z*Q@;av@wR#4bZ!((uXLyTUgWwfNeI8HEPdX%zauwFrIfnEkJ~ky;-kCv8K+@TTzkm z>&2&191qfLC#^q`=#u}-xS_}ZZ$6q4>Ub$63C%!ysDP1Sv;XU#;gWpkglZUQ{9?>* zA@C?v9urKCQ$Sh53cE|V(z;z~Ni2<3QR_;j5^axN1EH%^OWq-wLkyA1isM@9Uz6lC z@;OO?MCp@OjKViwV+O$(RzuW{IL4CYIQv}gvEVk?_i#c>GZ&mBHWM~X@z7dI&T%pe z;VzQ43l-W53yX+n|2yEzC$Jm{dFT_1)HXd{ar8g9%+(41$L%EsQwMJ1u%p@f0*|- zP1(+`PjyBJd6AW;&k@d^6ca$oM{(Vv2Zl|~RIn8Y6rpvN>v@xv6Q^Zq|8tpP>h{Qx z&M-Eo+~=fPfJPYcI2R>QVkggvJ@+%&3&g!Oe8I5?ShWcDK`Hu2YN|~KD150keWpgR z0?44pl*!8C`d;6MF){b8@F)af=J6-li?QzyTZ|iw95m<1Jw$b`Ph+C(1LE|jF;PDt z|1(Gik3$S$mjA?kP;8^$?9eWzlZI#}Z@Eg&hbZ%mU(o6nCtfx<_VCNeq2eGC!LojQ z852V>{iAj4Zu9)M&V}7jBvW+?Z$RUw5E^$usD3Z^T7iW8B&&14Z6B;VMQq(CWeYS6 z;6Okc!Oy-d3W}7=&H3UQKa(|xXUhPb&v1Zynvbi#9lQb}ooPPoe=vm)x(dCu@m!sZ;QFH#`_jLnw4l-x zX7#rVJXHFD(Bi>xT`+|&OJBUE&~;9*NMFpeB>ZUA$j*sty*oV<7}f2O3F0MPF1BUMsCdQqZH;;0zYn{os%8>v9^$VESRNaJjR;F!4v1=Chd1kRZqEAK=!KFg4)C z`nLM!(fXrJU$g6;FUfG*1!53mP;Q4FiLI*JC-{(fH(;QKMZS{b>&5Dy@F)O7P{h;& zvW<(-{qj*~`VoQBJpCjn81^ChV%sp#y1@o%$=&&pA}CSU0o(V!?czY!kKTt|iKhPZ ztpbhvX!wVc-t5Hy+FNv}RD}txd_C5z%g=IYAS!{Yd55oI(lADBMZdY`9YqlQc~jEeSWH>(74ER5Q$+>F{*S0nFvGI|{)m zXY8sii$}YZjZT0I&jNzOQCql$3!T(SfM@LBHKYHI z4r!T;*>eXU{CToaAKV(xKunH7iLn{Qs4R?Z{vmwNgTyA1CjSqft|-4OA}$#;3*I%T zQqRx;MNe}n6b_kv45(o{?(mG~zb|&w-)P-{pF@E5FNfgY6)uz=tp0fdl(avE3shdi zHXYBp{*bi%--1kJ*0|gevkH*WpTY%D0T<&Yuy@ssMW(UVb;3hCR<|Dp0X#pS7@6lU z(ZY1$)aVpU8IsohVmyQUaN~0n-k%q%y1uG)bC7TJ;r&CjK>k~_Afq*53XEcYTFTdE zw#UfAY&JCj%ffyd@Ad{ABX>|6&n`Xx1&eRdW?+Dth2v(l1>@Jg9=m>Vr}!)-(?*@V zp;ZPIzIfL<6MJD(Q2LkzR(lFzQ(Xiygf6z}tVPjG5luU31C?L85s5rJkE=TGc@Dhc zFv=5=?L1hnZ6Na&ts*g{UUF;&iL%V>(yVcJkbP)PkdZu}UD9dWZ5f5*bWEGHnM(3I zJRM-!hZwz7!LB`BN|5eS#(PprH<#qlfRRF-isyf=nDqRu?@@Q`d4AvRx~A=ibN##1 z(VYFjW5%uY>?ahMEcy$MQAsVeru39;8Q#pj-KI)L_q7&~tj({g%KKZqyX=nJvs0F{ z-)R-4Ubm0IM`Cxwc0?;ixf`!5g^r+suiwZ*N2YBVnkWh%K82-@5T={ew&dDghE5=* z-92mmMW6tJQXRqGYo_fs^hUj0UuodtHSlM_?%~J`&qxhpP};W>^vta?GX^8ZwKo4M zh^LQX>VzAH00q3}G724o{_aBHvCaisT4j$h68dv@l$EAO&_|H#hr#qdn$-8_!38;o6aAkXfS-u^IM{q&>jd(JQPBx+1$nj!W=`LI&9_EpOg6_Xp+{ z^~dq=Tlyi(?P7$*=Vh7SI`ki~y9j$XDHy{xA0WFB`N!V_o_C>kl=zti=jx8Dixtm^ zhfbS&I3v8f1>@@X4a2RHqV#xmc?XXkm>gC`F~_0^h;N!L)!XB0HM=qleAE;BNm)-qhw(p1}K;^2Gm~Tm5H% zl8U~Sv++L)9sVPEOx@B6*BHx(e0j`>JIC0s(Hw@Bj_sJ7C>YJm<14m?xws^mb&kk@ zIdhs6_pBCP+IKQnrdkG%MhNjDk*n#p@>;mwzV*1hoZcMQF%68FHY!kNG zbJlZq9l30xwr-nA{JHHH!PX)?joMiJ8Mbt=Iw||SQSA8fqvw-)-Q+}dNPX4qcu@yc zoxGHX`nWm^caiXPF~q^H;PAYAA0`+($wb?n?oKg(Ghu$Fy1SgZNeyK}9_+3neTKo4 z>oIhaAb2SNFM-$b!00ypy!n)QMC(m68+J`xmgRMa7_PLc9CCe4nMH}ZMQVzp;lgtx z4k*FMQ=8EO)^aP?*>$=Mo1}Te17mX@ahjBU>Xhm>M{}0bLgTt+3DXLv z!hu~|bDH$}vJSCHHT4TNDVpiDMr8PyhVtrKUK@-Oau21l@%rU956w``{B-Rc%swTHXo`b0(BuX|)(q2{zDJ>LU_50S21xg>GkA`Z|Y==8-328b$p|TiT5q<#Ak#td?xPnaMoWT6Z>SwxztVIv1 zdf5a1Em5z;&sfby56&!ne;4EJ%>$Lnz=b?<{ClL?d!`>k=nFj-y>Oe~Xq zK#Q=TAk%^gd7KSpjcioa~(I7HuiRsE5 z&ePWioMy-}*z!SYA5ckf^s)#8#%d56IH%z&p|@Z()<+yfvH}% z$?mCZ7|^c%Tm84u?yBp0Ka49JP==iXMjy*9SGVQv%WLQ?yXJahtSf<(lU`4)GLIF4 zeluUA8v?!x$$mzq);OkwT?1h1i<(g4=Aa56IVVM;^LJUTWAw8WJ4f*a;&awP2hgfg z14r2Q&?Gh~Z1r^5H>j#eNtaOF4tT;`Q>nNS;tOr%jGg>&7+`e9YgqL#K+J8+Db z{LYldwHJ1b893#Nvc;rRH!{(-l~!9o`#w7oeyzSkQJfQN@1VYF-m>I~n^6ta3@y&t z@W-0`?v%FWm*rS|;B=zqTF#+3Zrgcx zjc978P8p@fEv?yAy>@oQd4z)}sdgqKR}r@6$c#?cthOlJejhyXQLB&sRC!67Ny#GR zsG!IXc#r&i*tvcYaUY*BBx9w>xZ)8!Zm9z#k?U*!s9>mA@=!);2EIUJ$)$9bC{%`L z^j-@IX|Bh)G>Lsw8ch|y%?auRS|yH1F9binVA6B5mhT|U7C+e=#bhX`&;SK$E|fS; zKm{Mr?i!Y@@tjkY;ho9dh|eDqwJlcm4V@EqU-NdvJm>ld!hJEg;k$wWLEthy&zvYf zz?5gm9F)oE@=})>OH2eZav;^Ko8+YwGKFnAr&GA_fOWEGx2*ZLkRW8X7r>@VO?5WQh` z`*kL|zDVCw%3K6(r?CE};28Xj(J{RYVs<5W4EJ*sDl+21aOY)+UxL?yd_;!qF@=Ubi&<4Ta z{ENx`EE8Y%F<*BH_|Li&+S||W!Nf1={Lp&9FOFc%fnTafAC>pIfXJ2Pn+PU0%vdJW>*)1oqt8ufkZjx#L`$Oz~sR6qTBmTKBrI zIB1)b2K5*DVTm&)eb;WFEw%xEX?8p|Jx*&tlQkL1b%7LD`PpA{EpZN)1#hpE_g~k3 zd8zYoiD(`mDX{I+h13uoG(rn9Y|AFG-ejEz`DM*r-erza@(MLxQkz)&=~X5L(NKHt zu8-m%U-@QF69b8fx>+ue1f&JSy&36@Z4bmF{V~$ zK4}CO;p+Xng-_=E3wU}YM#wfaKX7u_E$51I#RIyWyFHg|5(U0w6(Ugbu@P} zW)N_2(0Bi5eyV!zimQz0V-k09HYwx6v1&6WS5lBz>rSLuPFG!_msZGLEnW&&0RELC zZNwyXVw{C zJ5XuUVk*AvosHyv{?Lu3u$df;MP95#s--jHF4~pilFhQsc;bm>U1V(L>`KTqm0IF+ zHtd<K`YbODQ6&3 zTw1qffz0=L#~f^`xS}^3Ha)4+GEJQ}bpO`dVqeF|btaZi*T}yH2fSDBIil z!S7Qt#k5AEG-dcL5bKu+%|(`+Qg6K;nn)3P6B!o2-uej6g^!^W1IC(8o7|SPd$uzx zl_*U7ym|?9YFUL>@*=|!*4o7h0qb#7?Z7MVsx)@U6AV#2i| z8pAFc8h_uE@*7B((lyO^@e`X)!gXrs=2m+6X6X|iK5Ei@h zCr2_BFY|l$j&x2jv64=IdH8oU+wItJ{?cK+rtl`^_FrSn8_L%d?V=y}YN^iD@8OTi zPP^zEaZBe&?~jm+%16CLU0W__<~5rtn~y6do`2dQ?q`}sakSRyDfQiqp&ujTwM3^{ zCM075+N!AXO834Q!{m}RQf8~w4p|K`Z0KLt9~B@?wqXG7ubK_BP-TOG-IaZ@Gh6RV-roz| z!0rvEs{t6`AGMG##*q%1X?~v<@~mqenPYk8A`EF&hU6l(myFmnHZ6uOp-Nugndau0 z=cNan-z!Qi@hbN@0%C6w*co59H5b$FCzXB7D@r>pEQ`BPl7n9;FIiJGQqOV~tcw-# z45jWKof=|AXg?cll^vXEOle1{2}0fr?}c2>OZ}Bf#W7CJ1a}AOd}=lJ>EvY*7~||o zKGM#1KDzzf#Ois(j<%t-3QlRtx5NKr>{7Hy+|oc<9EyN_))PLViq2CQP`F&T{p!jV zU7oyVU(-SB{I&UW>$LO-pDK#ZB}!SZflH8SSEUJsD7*cQy!4iGKs9=FY{t6ARU))t zN;G<_e>OUoFVwanMvhT0U0Zzq3~x|yf6-vjy0|gC#g~*|^b{eSgp!O@4FT5K1uAnS zYiaNrDWx!B2mT7^5w&07V0UHmg8v(y@4v5%IaUDk>MQ(m!CfK7LSQ}3(~_v}^`>ogu!(B}d)0y3Ei}B# z*@dPx==t`-_yMz+(|w8Wh0VkhfxZ^f_Ipxwi`)xX2ewglLCzRR`w)xXw|g|e_r5cS zULkSTjdmtVK)mOJ10kl^;)9a4Uk)ea1_$BpC+`(JaWu3(cOy&L9K^L-e~$nwmqko( z_dfa^CqI2}0$$#+J1vCK?Aj!2w|qX$8$Sq((11PM6ARzK1?*7(NGxI(&n~zW{IP|3 zA-V*UqgW4>DUtKYl*uY^iesMl>-{3z*YjxE=Y>_620`95Gj^z?<|o88Bp`TzQXX?C zE}su3%ndC>BxNa+xRoMgCGUym`+MXp&ov6qsp1pIy>Ec&)fc*^8!g?fC&GqT_bceB zAxC{N?B<_z1cZrC{j`nvo}ij0h@^qX_Ot53Wj#EMztR}=()8MvO;-_C+OnUOVmj6RjSk=xA}8oWWjDJQg1Gb)yPUtHhk5h_`Wzc1b1_d)$*v0#Pc))Ga?D(YIL0se)YT~X-s5(U|1Y!riJ zpsu_O6;gl$?4-B&B+4MK;IG?-l*bHio$w1CI ziThZtiNQ8DO17~3Z4Kf>>w%4F5B$;dR1MPgk~01d^t`e+@4%Hz8W z=~uC=BChwMnPM%Z2Pe+G2F|wgGZ<0mRYSg7+VwMOt;Y1T&)Q2R zV~GAV?c%>`J9<cxImkd-U5j zv8$7DEiPzz_5#a?TozYILf-v_@V7j}KYP4ZEb_})cN|c9{HBihw z7Tl(x?uAIY#U$HY+`;1kMLd`|wL5>j@g;t#M?>97A*F)@Zp#YR9%dAhqpV8j)O7k% zjwOfbqg6eaEzvFcRf1nj+PK8=pp;OB6$u$L5wQBSz#-F_#m%eJQYd=0w%X&=Se$4w z1-iOVK05r1r((2#t1Qy1}Y4&$lVDhAr_I`|Ezp%rzT ze~-amMcMK8CK{^2gR{KGhuiGg#oh>XWg%AR6w#?8Gu7=gZr18^ozBy5h%X%$zeXw9 z_H+~MWAf7Ni*u9cL%6ERW zgZUH7dvD=%?p77H&fqQfiZOO+2dmgV-7brGMbd&;`o1LBjy{vZRNXyvq~#ONd*v1y z9M08-R3(L=Mj!u`ESzQj`>0kbOP=&aKlKoki&!Nv5-R%YAR{&Xh>L`6@0$IcU=YKv zv&3Axfo-1)Fiy8|xSUCWiV?%A$Ne5eOKIBTlDgaay=(jxi2JJWy$(&uBXTTVy+qmS z=PxMns(r=*#<3LYMJ#Xt1y1pX6Bt)W+&C#-^_3+@65QOXjwN>nc!mpJm`wNgnz+pT zWBOY^>IFH=a;t)rjuhK_e{oHZ?LbzYVr~vld$mJUR&I);WKd+kid|-_6)CfC66qq? zT>I6y63Iy~`}i#T!rF66EiqE5A@5L-)HgZ9mjOIYP7+^9z1-OdIs@U2MMpsRnQh)N z_?57zdk53*Kq`4R{8K}qus&(%Xd3eUK8)x`+->j<~`l}Q~e^+Yi{mp>6 zk}#;p7F7JH-yi8*^{hmIF>5hI)(_)2e5pKYY|H_?_%fZsh0-9oItVmr(!N+kS z15;Kf%mz((1CytCRui@;0gNqTo-_pL4D8IlKzs>9`c3n6^m%y04Rq~UAqb@JH;J-Y zI%iHLci};kh|QAY=9S7ra;pAjVhHY`xf*em1vP{k)1-INzC98hH<&W>G^Ls|YHm0d zcjg`<*!R<;@={?cBNN^p>ez5vs^Tew#`6vHWUfEvX>!@})bdpm7F3F+QQ=H+7yD*5 zMP?>Kh0G?KsqPny?p#FrW{9|2FdPx|YQ}BDvNi{Fd@v+S0&fg6ODfuX#|ynGL*n zdpP?%b%UM-Q5p=;C4{>$(Zvx`!4k}R%$LM}bRpn8pAA6Y>7xj`v5vL%>{^rCLfP~@ zH-9Njmae|nhbirMh~E($oeyr9yYs2+?bZJ?yk4yqoOb>7rc{`wasa};QR7ar%N2wn zl#nkVtoWI8`c;2w#qx;*wvzgaOQ%N#q+Nk0(xd;kEZx*~e8^V|_pj97n1o-<;jDpSCl17gCMK`h;-?(Ztnn2z?PU2jYlugN*C z;GEhHN0aMA{9R@-}3IcTp;08Lp8Jptj>+{tI%)l=t$go4c+q8Leu)8&rIrV zjY%Iv^w-9$HYSrdsVckI4LB~444bo)u?+~$01G?5XvS00F>P^4-rc*&+tY5e5Fk?kk_?pp=eygFm!K{w-Rx^ zeYe^SeLAW0F2mq%?^N#XZiW>K!I)cSzH%gHu;vDV$n%k1L*$0jO) zZ_fexsgA{A{Hsm$f1XtM|EXir`gZ@cf>x-kE25~Peyo!k-PVW``m?WSh}1*Lfix1s zsq|ygB7#cv=Qg_3X~hm0anvo#d0lS)PI;Kd(0S2250}WOiJH7?_>f(7t$Is@e+GZ;T0RTOL{hN! ztVf&wLSIC1A&3yYf3MR_C2$**zjH7(AP5K%_Nqfx%6R* z1=Y|*c`QvVX*#=7L33$xYVu+reOY!)l++62t$l(Ddb|ah4*iYwiBg^tyHlkm>kLP| z*Sr#KA8H&O^yEaVh)A7V`a{f{tjv*jY3|}7?4Rk#KLhxoOH-p@IktVQ5+i^w6Th)M zk0%r7SwD2(X3BA+Cd`F z)LQ3to}36%2Co~H8mj$v?z5gEMi8t_jRLf9;zO3Qbz>r!RouF)otBmw8DCMLRG9`C zHZ5b*|3Kv&c@72a=?D$ipTJV~?$};$#4U280n95sr;|gg=~`}Mq0p0hk?d-&>2bOy zivsJUzZ+H|o4#T_#ZZ_2@Z-p$k=HfI%xYFYIDCz=-hB9+TX>9)OI@|T`chcok z=~U;GZ1%ZGc2KTX0YPAiS&?;-5kU~Atgi;>-N(VveQ+2w5W(zQsz@qJvzahP>I#B6 zdQqnQCd(W4h3Y5C<8Zr(-8q{e)a4PqM~DsIVZLuS!F7jcWK6Jax9@i%(LL?E7;408 z07xIw_Z^?WD|#8u>n#ZW)#t;iU=E};KOPOsmezVaD{JI)Fi=80citc6oQD+0C?GZyFme&r+fOj}(6`|`!>vyAt@&#=(_f57o&4JzN)#C z8Nl4w%IKf-zV=mD9Z{4qKQaz#(~Jzw{Z4WT&8FEqw!xzbDN(7D<>nR)dRE!j8^cCy z)~u?F-MTjKC$O@-j>8Z_Swx%wS-2)|X}I^U>|^BSv&Z!+rnm$T>6ht$9$tMm_dheh zHs7DFO}}_vi6EO^1^A1Do5lrirQ>Ew?Wm+n>Oo{GTsy_yvc#UNw-^>D$2tlO)O#6@ z>I2~G9Fi6F$ZD_-_pj2|s0!u$=^#YmjlrkJtT{rgi-&s@<&^CN^fYtKl&IGaBVYio z^L3%?L*@Ra-y64eP>+Vk{^aE9Pr<`UcK!khsR?W3F!fLo(7T<9lEvCbCl1Omn7%83 z?!RoZ8snx#JU-4q42I{PE&SoRQ9ChhVLs|K6j4I#%5^K#Ln(t|Hz>r#GS^t@5;C}G?xa1bhY4GL% zKwHPDjnz3R3>pXC2fqNK>G9bz`&bUkmgviIFt2heG|kWp zi@eop;6WuGdp-R{BWC&g`(1F?a=`8uGmXmnF!vzqpBnVL1FvN^8nlpYH!=LK9}pvp zmdNt~e74Fwv*gJe-=Z53nRPhS$VREJe)F4- zfGhjaN)-(9x`<_NvL7$cH1r2d8to(pwb?!p^Oi7eY?my0wR;Oig$XjRd%7zNx>m4W z3}}SOwh%&Ryhw#8b{o_0isMb1w5_(Pu0fYuD>I0vTibp4!E}X_EO_^e^X-Gp7j%>Y zrKFD06s;&JJvd&SCOZ!>V#TLsm}$9O$Me5fd&e+I*QHCiyKLLGU0t?q+qT(NS+?C} z+g<3gZQC}wG`08H=e#rDH)qdv-kIylKbiR}pNPEgh!rc=Ql|{-#bM@=!`os_S_Du8 zCAsF&MfC*t9~SUOx;ce`v+JG`fVe)=49=|PQCejDlGnmNEjY?{_@r5t% zOI31#J_sev2*;&n1OBd<9f-~{wyO}3RUTGc@oltZml>DY%u>4Qv<1s`7Y-KvIuDSw z)DK1a3~rLZqJG)N!W}5a+8*>3wppsmIV%D-8E`?Gv+zOGT>lEPD|*uZBRzMzL|Qm>r{0cc;=B&*U?E`GhBva z5Rlrq?-}Gnj!n4iyFeY%)g#$|vss}zx^k$x`0$`Hd#e}2aWP!vdJ$xDyWo`4yp25v z0lwd%qHtVu7H+nbZQ_1#y!Cs1eaG)dl7J42d7r+IhNdO_-Cb2%?P*yB0ZZEk|0uS> zS0<^vgvz6Y216P|=b<#N&1FD~>VZ0}G7tBXbM7b-tT2p;(;SD1G_eaT2|{J~%N%fnjHW}XXUvrEafpB=sH}rqqWeJTmcs~#P&B0>mlTYg;>_$_ zs6dRg6Bz3idD0|9$G%s{$J=&xmalaSl;EEau%FQG4OnRylw=me+k23 z2Ppv_6#uIPE!JTsUPm}K=mTY(&xxu_`3-BGr*pX{Dtn`VX}8KzMc;5vjSW*iIl6HauysE^bU_mBo|KOsPw>EKi`Qv*1%PswXgQ~0ip{@DH z($cyj8ng=HbvRmKD6Q_5s-66{K!#-j;WWm$E9QvdvW020x?dbUue(IhUn&%7=PtD7 z{MIvRP7~Rjhg_R!qcJ%-zkpH&*}|b)O19$xqY5C5l>lmmqtpu#{3=mmdR;g}UmT90m%q>4pLat(3}w^7sV07I%4>q3ru%x2NQgp;62p*l^x*kKGj23cfhK`88@Wh9m!+Wa z4#2oqr4HA7ixVKl-d%XQC9YQvk+Ev~6IMyQu)^usarw%gCZ)L9KilRv;#P?TiwgjF zSBI1|hl-|}8pOh0Bb=2F{H*_p?rUn;V16Rm^oI)&Q&A#U(Z?xaTas0~oU*_Y>aYykZvY!v3Pcdv}2sj+!!T?J9GUfOTR z_g+B;6}Mk#TW0E{I;+^K!}!mEdP_I?_JXeKyAJmzfy9n3~!sJ&M7 z?Oa7pA~`;md%1NOidwN<%JPTfry^%w9J1|R(xBmlft-CRD zha9h<*LMbu2_L~b8|oeT^?F1Fi4Y$7^Ce0wG5erbWorpd;mU09#qjGETZ?{(EsAIl zD`1XjWLV_?Fvs>6(CI^j5ATopiAhg0fZXTL-CNnrJeCpLycwY>D(pUSumP3_72p9J&u zzZHM`e=!`BceJzr^t!V!`Tv&8jcQtIpUA|!Y?Tlbgs1|zmJBMXw&0vy;cffme(~Gnq9SKdcxq-<9 z@5@>JWb?23NnU2Z_uE0EFN0U#;b&Ve`eEr!z3mN?`D}k*VVSNX^t}Kbc+dHEjoUgL zH{mlW>QeAF7^(7SKF)dzquK|%F}=p!8*YTq+2&q9MEke3k9)*D8t^%Ph5QQUrg*g@ zL@y1nB_&6X;BngnZ7nvoXw8pDduB52j-Ul6p7ECt|L`yf=O^ggUGa0r3p_j6txUBI_(XbEgteLoUGxR zLy_2|38_&gAmL&zii=TMoQBD&)ylQm8NnP_S0q#nMrwW`&Tuc+VrH_S#E2L8 zWZz>!yy8BZ?++|Ri@@nsSHaPWbt2_`)vm&t8f?rfJOL@HhTEH;!&Rv@|GqZTo-D!yTRy%z~laA)6RTvM6gC4D= zTs6HnCEOM2dqar)p`B>`i?!~V+fxGpK?YISq&zxNt4-XZ3`LRgr6s#q z)y*%ObHjue!x4E9&usw!;>kgqlQk`T&=}P%RUEg z(o4si1DjZe4LHN!@6&QJ*`vH(&wmg;TWJDhE8Vjn2+D8YIdoQGxSq~+s6$}j+1h?K zw_EG&WG&zQoGvrYUPF`3V=C7)p>hlPt%<6|huK%w$g)xP)B0B@)ak_WgQZ5ZZlA+` zILA*BfeO)+IA~B6IXm$J8MDL)5WP{R5iCHJDzgVAec}-lHXQ4vc70L*!_297tnZgo z6n9z>A^4}943e_=yR$;wAkBfsH|ncb$v|MAEwc^PJbd6ez|mnX>)RcUa0?Tszyh3Q zo8R|G%x^$F#0}%GaF@XD;>jdEWV3yqsmiidxNW=MdiOOY@$WdhjDLE!$W8=v@$>oX9N#-9c<&;IAcu*}W2( zb-5GUEX$nMVIkWMg$D83P0nBnL@`pt98%j3$1<7UQ&dxXwA`_Q5D|JkBJ-k5MI<`; zjSQgtV0N!o8!~Ga@yXsWonwo?cpMeAhFGYko`noEiK5Sfypc;}7s7gkn6^Od`U;Av zsisN4ia>CN8*?D2_tSwdQMn@P(GB0jbXXk`;XQ&p&>3wKya6HcBv0eIR2zIm?&)?@ z%k>1PoreVg@26dS9VTr}ak%oNwV+eR7jYwLxn3jDH!FUBEH)Vc0(h=J*B3?L|E`Yw z??d5#S2vz3^2qfvAaqy>0q<)W3Z0z?E;EZ7@W=5R8VQhf021e-&qzk>jJCi(J&;|6 z^FXk2nT&>iwjI8>`#!u3o??H|?yiLfr^6wVCZ_YIlvL#GS*Fpxj;~LQNPVVUT*=@g z$fQfs&L}WJLJvO-LkUH%moG~daTJ(rpQ4c}Wg?3|m4-rUy-xQowbmz(ouNs(DI7}O zBrw4B0$%^dysQKJ;O@@%^bQpiPcIHTzB-g$CLOnsEHw2~V0g9%&+B#~bhQ{&q}9wB zwk(usRH4m2=;^6iEq{@%((|lW_>jb0{Mt*SB(y3a5n;kBxY9kP32r+^uC|rDXV{Gm zf?aF<8v5ei?qd?6mAeB$CrVNuD-1*0bC5`C?bVT%2c%Pc_l zCH!3RB^BXdH{FLAW%I;q8GJiZxBth}bnSdoL|TVc#>Qy057okV0p+x2>)W2=y>xr) zRD92rPXgS0!Yl}96}ls3a9k5&QXHW)`G;3F!#6F;b0k>O2ScCX4mHn(bc!tsw*`D8 zxpRlYU{i9EjF^BJPeVNmkvsk3mXuJhO#T z0#Z>+WQ#yX*r~Hn^P&_*Y1u{m7Ho!s%+WDmA$wynUn9#>E|6(OH+m#FLJ6*O{O?-IA}o*k@1mKMu^#(h`4BQHrX;m)t)0nzlY_qD4|=Fwx|f% zmF{d|jLj&+(!#;CNTXE?sYxwrR)eFtIzu#?fh3+T0_L_EJw>|4C!F5AFY|^-OKJU_Y1ZdV zoQ{9~UN&9%^dY8KrUYdpx_`3~zg{T1U-FZ^gpy~67Yq6p4<=tCZn2WYE!E<4(0-iv zi6XC;Hun4qRBd3ya3hWE&{Uoi>aI6eoeDHv@KVp!kh#A>pjwKgh4P##`W!~$(@{L3 zp!>8GY%yyqUvYNE%Fh8&eKK7nmR=Duw{y=CBU>-@nc?|v;Z|p&K4iF36Ya!$agMB}RVh_FuF z;$eFBMl27CEb3CMi;gOSYX{*5BLT*R1tTKe&Cml}GEB%?ORXr;PqPCxn8}Pjro@lv z5`C@Y@TqH+n!PfdX%S^mbz}W-xj04OKVmsM2iNU1#60lGVsKJ8yvnCbg3>NZCmnFh zHfRlILeq2vIdzuGYzvyqfg7T%jMbTvZQjuieOS}xU_7B)XfsoWAfO-Hs8}R@V8HX| zq-pQb_-E)7k*_7XjjCJ$RsSeK{@p}pO)OGi1m7+j&u2U*Sv!wRp;%Jib{DE zm6$=ww_ma^1QOSR-7sVcGR2SDA{42TuJzstdz+)mchrrzvh&wQJ|sQAu=R|>k5Rt1 zWRAj*_P?f9m|BlAO}qSHKJAF3!RuDMB_^Zkh;f8>g>#y8yfA46T?wGmgravm(1jjJ zOHzZ8F=Fr>>|T-`s9akPw$+6m5V%Q^ca^f)qaiKc=>{De(v`m1Qj@lA3-Dk~BLQP9 zq`kr>n>Pj;(pBN*7kLDhHo+{G$?%0|PTuGp^Gan674wB$8xB5n!`bgS9kAt|)K3L| zV33z1nh0 zywc>6QOuC{YhY{qP~isGAa+ZP2hr#;(P$UWr4P4eV3t$6o9*jc2n)^?mE!nrPDx(M zqz|Z&JhMcQqeKvs4~0pr_~7mdQbPB6u}`=}VJ#APEf%nPgj(r*!s#?$J&$L47DoA2y=Uw+flN|QI+oIrX2!KHd_DnZ(dge81 zm`AGKjtP4^rZp{?N4EQXOsjMJKgz(PC1+&IPdJhDZ@Ibuec>Y~dlMrI18e#}t$7qp z46JSbRcQQGVyM}uA&a5-f*GRD} zxqW|9I>Xj9$SUADyx`bcCx;4{q~x|MizPk>%@;55A_l!}xb(z6{`BOSs(Oj8fl8LAJb2eqq4 zI2M5#)4yc}Du?3Ti;$Wz28#`Fhnuav=T$(2y%Nr?!zesk>`~yhPns`L6hCH~rvaX2kH#hrgcHWAQ@5^l7XmJ!@nSDs zl_ug?NZ@(t5N2?nEKb5*T$Z-Ne!VcL@zggA<7SYWGYc}O3uZAU6%;TPcyOiRp{aTI za}1{VVLE4hBo7*8o_Dh5Xty$c#OIAuyLjIN(6+zNS zuRURB^8*=HVoTBeC=75L`Au?0S-Z3W@U@G)2t z0qGA^Zk218y?H-*5&-;()J?Lsa|*o*+H#XgIY&q&6f88=4u-q~*k$Qa?+eVK#PwYC z4y9bJ^n6%pOOylZw|J`G!Lv1!rSW7r)ie#fK_XY-o4HU8fuyLQH02!BI|o<;>zsI$ zm)GL+m#SsgFNHl_;o-AKChpE>^O*(@=Bdcg(Nb=!yS_G$N+5Dyz|gsdIx-C zW&x)Wp|R zxf|Mj&Cl2r(kttNybG_F?I3e_3y6+wQU0+bz{YrT8}<8?7^Kt<4tOrRSRol9{fIr@ zJ3{|v1}zbvlBicW~Q#F%V%F z_($%+!a|Nh@%&bHM{ds6`AQYOI=j~efttH_bpWVVDPZcd^TQL*=6E5j=?UL9d_vAMq#(jny=7{6gRn{@W+ z-l|mQ58Ko%w(3oBf1rJxx$d)z*YMwA^Kga{>>muGILJ$lJ*=%Va=UL2whtjvt@BXX z0XAbtL=DWUfIv$M6ltEi2V381XTXQ+)hYed!T;mjMVC$de*4Ln7=Zn|Mnm;K8{?R` z+dG;#IeiXl=>O_4ME>=Oi0h}oh=H@6<6p3Ib8-k z6me-RR>2l}7fPuSy5%O2kECpA?kC_^g#k)s`MK`{LWkq+>yJgu%PEV+W?wi0ZE*AC zr}Txs%fL24kjS=dZBPc7m#&c^aHTXy@(=6<>iqr=r$oEr5IdYUlP8-&g*QitdF#1G zYHuWIf{jMyHRl$U+dBY}j001s-_tAY+%={MXG;_X>Fo)WGYW@f++PVYifLI&}JM=CS^^ng0*_ z%l|3t|G#*D=7Na3k%|2uJ2C%=e51mjk@p!@Lq$XZvGc`8iM)^AHe_J5X!l=B`I*dG zxN5DnXXin5y#;?IhG_=<6*-LEE7jxH^l&`m?)LNzxQq26VkpYZP z!`x&RI`4MVB=F=#zb2UOi(yx6n~Gdu?#>WDH_2}9ln?J+Sn0Qs{da#Wixbea2r(u@ zcjv?h>l89E?y$2dbS23utPm;$0ci^NWZgWEiU!)ETr>p|6@9mq8m?{M9;5F?RS>Y| z%<4ubj`ZvAqqIU!0#Y@F>m*qNbTrAjzeoG}xa0 z1~-1HkWy8TTo*a6y2MJ;Q%As<Zj7lRC&@FW#za04cl)zZ(x5!R!T!T zL+LZJNq>tR{D-=De-~LhM-s+={+CB>XZcZh5(-=`VPu3T_Z8C7&=vVxD!wlTDVK$= ziIhp|$gWB3jHHDPxJrD4qY}jGPl^#1@SYT53=*;(#*BCdr=hp;tCD?5gj>?l+VsQtpk57c43m)}5RDT;P1@b1x8y z7nby_q;7QS-W?0VR9!uM4SZot@%d#D&W@4HmBNG@$^wO1At44>|NUu%dm{dT?FAh# zC4&`dP>3smXxv*hHQ0`wP`si_7$esb9m(T@Hc*Y>T9pE+?D>PqV*x9~Fma{}_WK$; z>w9`Y_i>4I$PNJ$C_9?<^9;%Il4~t+O726oEliAQEdTzG<~;VV7L^SVgIC&TJ7H19 zFqfh5AME(=LGT~p@P66wegh%D^c7=tfnhFk69o@_M0(`YWSr)B&poYmqAM`stIKIQxP6WG2ogV>@2UJKXdfcejcrSPQSZ|FH>cN!YD1- z*}v2Wm=3B%LY2RczwY-L^HRuz8j2iW?%gYKa;Fm5r*B)dI-yTifk+x^#X&8VPqV~E zp3#2xxJ3-n!V%rp#N0;SE<#U_(9Fm`#{IKd7*$K3Y32R52gZLWkNx*)^;c3Q2-wZ? zBLr`fb-P9p+CWSRYW-*--A4G{2iq5bR1jVgC$18Mh@#XbpGA8Fs_SQ8LP6cPnu44PCAuhI5O^wBFcGL?S9)o}P zs*+^tdMbICIELlr?+!Yle77+5Ns61x&eULHC*-(J2g?`X;&Qd;ZGy_Q< zTQ{U|2dYL%YimXp4;o^ZA9~lq?a2T%i`y`RTYR~bt*A(mVJfNgH=@YG_+u%6Wx06zPDSeZcty+d$%*!1j$3QNl1R3d= zcrt#10}UA}7cZ(2iK?F5|DR?Kd=e`H2CcTuoB8W>rvR6^4)q|y` zN#}Fzgx~*^G34u?IotY7uC2dKuK)1N`eeS#Ia-+5I-3~(OWf?gh5`SoKU7Z@S5-e9 z#W6{Ra=BNkn2gkn;hywbSf&*yMP!& zRI-}~)CuZ<7=jqJr`WLrUlb-M_=-UAG;l35?xY_=aEMAhTpxkb;#OWVhg$t2I1m-I z9I8{l#YFw*X*86X)f@t6XJyLTbY8!k1*32-g|)3$euSsPFr&mytFy{5L##)|v@hlAwS%ZAvzUkgDgCi?R;NCk(r+$VZ_`&fS`)~UIkpTxU((5j z0>qApv2(0;ie-5>(9!WphJ~fC)Y(QWTJ^g&D{WSfSiOY{=o;JO5%F2&0x!vG8KcF4 zk}#^m!;DYul&junE!i@XAfQ%Moqa4quN;do#4ZUHS5X(&-pfM{LHULtmnG_hU`aiG z3g%eEjhOwrN+m4ji`WnLRt}4SX_l!VdFk~BfRlMPK`pJ#} zM^7;ANa?dYGm#;>< z6IC}9`IcFgLf#w3t+pon*reCg@*AhvIaHs$YVXvfWol$ojKUnQ3d~kqR^zIPhT=>1 zC%_YrZdMm&T!;4aZy*L2-I$#z>^OI1-qqRSei9a$1ShZas}7Xf_ql%7udYusrZiI< z`5g!&(>C`!VbRTi?=blI)zuSna(7*^?dh>gu+Sf47VBYEMlNKB`GEKl=0c|&l_n>- zqvwA*G=BW3Zsnh3Y!_2?yxqJLz{+D~e})=~X>stM8u;3S{Sqqd_4wmGymRp=Cfg(W zJ!*665jn76xmUxpF(kl8SPw@(wqkM|#Hc&WjDxRVoyMMYp*|!x#ob6W%^Q-m=rx+X zP5!V+`$1!ytZ-EP>C6#h5JW@50!ay_EU}6p%%9%kj&b8VO0IUVOSpN~jyFF3)L?z2 zeJTrqbnwngti57TjVu>TU8jH@&>peyaDj(r7@t)69a@$<+=J7>mvt0reMfj6dT-vZ zHw!8TJi=D7uj@qC&vfCKV{H2mj{E)?wlB55cYlg|^W&!tn}7CN0)NX*m-s*STE-Sm zMs}_yjvn*^hEC3o21cI)oKH0z+t0I3_^+=_{@Grst$JyzpnjYi$1`&}#Wz`GFf}v@ z6*|PTNSBH@C_-DL8!}i}uAnH|WsYT%6iZKFPG(vlBSJ|EAY4JYm!e-G(TDzEun1KY zt{geUpJM0hoK)NNLGn8tBS~vuma%+c@Vcyj&`s%Bu&Zu7$olBKCiB;E7dzBvBM4A{ zrNnJya49f2E{Ghq)CNGpHUW^aE*233FhxZVh8b{{UG|B~g$56au3{6q7h@M|5y@RL zdlF%0nY?uefu8~a;H=yQM$odSOOYY_`l>9vdAku$iXbsN(jYP04w#)4+mN_iR|T=Z z^0p~)9k_A3nV-s{tG7=LyoK)kl4)PcJ9vKf4Mq?{XAjiwCpq>wj| z`E{-ya+8ps>^6rp9y_ykSu{4rI9tEpCJgh8>?)h6y3OtRrS1)L!`!{EN#Z^(D!IoOqn@&QEKRI}iHAk-GD}iJqc%bEK64+QM);)a=^i3UxY%OMbtb~BWUz{C z<+_qGXD6_={3bUtZ8XcVL;Bkwbb8vbaEv^_cv~;iByU5; zWVJ)qcjhJ#;yRIthK?NazjN)J{G!2QvsErVD8JeA7vBYBu+-^ zs=nkN>mm|fG#5RM-Rc7PH4g|SfOUr}Gd$2dtjD9_YUS0Fy-h~iOP^>}_m)QrfE z(_*PdOTUTxOAQ2XMd%O?t`Sv$J#4W7w_OVa-%Hi~R=m!@}Nz`O+VJ2#jrd(PH*>Ww=jwd9)YW53=%7)jq{wZLnRDziRaA!Dx5sp*G!l zW}iw>%)ppgV`2oxzR6&GR82YIo{;JFA^C%e$uZ1RI_n5^D=fJ*!Y4xp7rxXSE69h{ zkn0wf=svHrO9eyo0+P#Q#M%{yt5gH9B8bphPsgnn9MwHsRneW6PZQ=wsqf=x&)WKN z(V8TY)Kl118-i`-g3_?qc9}a?FTThcquC4Ga2E+k`ieA^kv>L3@x$G|7NK8l@qFm5N$vPI(D4{ocP?u7 zNBDi3I`yUc@%n*#@Ia{rXK-kp6fJabQ)F&Ml0|3cNC~1`NT4K+W1z(Ev8_f3d8={f z-$;?kT_mYoHHzpz9l3~jSN+Z_D|!wXSL@66=2X;wI@S{>+m`D#frW5h2NyHhM$`8G z9_=D}<)Y@S^ZaRE9g96eAx6&qn3(7^0=M4h7u@#4p4yLfChSVj3U|?3n!`6#4{}1X zivI0tGCs6`2PlK zFg6E^DvYV|CW&{sof11h+;+%st@SV3u~oXof-}||E%kS)H|NENB|Xh^aZ;~diqJ`% z2McblVbrLO*G!bA9kyrD*6J!UZ}G=A4$bb3lCZ(c5X-}9j&vT|@u^=*w>FPqgBWZA zGL+ycL${v=UBeo4TB?eT6ef0Z|3$GvQ=TC*9bJIP8cx*l1FuM%A-RkcluUrF=kAi63 z6a64``|f#&Xy~1m-z2;ur#+VJyit==O{$H##yLL@2(5Q1X25F!Kbz&Ps7ad@%)nh> zl@!C7v>m-#VpL;xSZ3T&jNHMH8{T|1&ugH^cJR3!5P3I5@IHD_-lM?XW588tCrTLb z@;7B~*vs@&7kB{XgNC zLPZ_BSq2my+qMGe02k1KCv8kjXa6C0I)dD232_zoBbG2R_IpjaQXS6Yqjyv}fBrx> zUzDA1;|q*b*ZxE=zwvTj_7ie`b^3zWd@l-NU9+#f*eMEOvRyuJifE(5f~npODz^AB zP7vy%2lGqz?+Te<}+$R?wzzh;d` zVOido$<*GI6{9KrFm-)QoYmZh9-^wD6cvyZtxS|2>DhC3t1Bqpk#CfZV^3VE=U;g2 z1Q?I7Aj&#F4mC_*KTZ zmZ3zHmEhXH9cdiN#*0UART~^ahsW4X0@|Yl+LH#f{f}4R22eUa%)3@$&@gpaVlG?t zN0l4NP9)x);Nm9^!-j}IJv9McYWxtMySBzl@K&){q}oPOJL+ivP6bbAXftL)dG6d`I$KwKDI)$!8NufU0~m@iN7Zc0Ukx!+A1?d)Za(gOW{(f})tARZ`9VosHQXL6I8_H9 zIM%hATGQR4C@mO$dp#;rXZ8aNDn&3Wx3=ctsWaRwA-q0qk?!niMG;&ua?}GYm z@_sl2iW2qR@-`+H6?9o$Q%4e{O#{81Q`H`PWCP1m1K&_4O&)5s74vg&4|d?V0dOAo zX1Z^sYQK(>^zKIJryXje+t@Bz&2!IpxYtTIem!IxY|FK*z5yd*0mwfHk9driIEZU~ zFr!!}e`BBR89$P!vE*!9WM_&oZAcGfjJOBGR@ZDNEi}6CRF4}K`&%jL0PYu#{eJ4y zx=bRUlaDX&spZ6l};1Z#OV|z(cogK&;p=S!6C5Kf24^R()N(8_eZGbO_Lhp zgI0HnJaLIKy(bAf7wW9~E&j(zq^!hVi11?^=YLad0bs96}2xV;ssOxj|#Y?N|$ ziFhI^SKRr*!N!!^vxR`_CQR5%jA+<#o5$u!IJ^Q20_}w+LyQmd@W(4o!BS&N5we^x z16s$*D%{OxgW%?$OprRmV@%Ol3k-;o1;(=L!k7~unJ1%RxrfaOkV!WgFPNkzApyCd zZh=j(;cWU2xVSN2*|=?e4MS;TbgaGB9K26!tS-?!|GX?10K4o6pHVRUTjc&fiNe3= zegCdI{7VW#2dQqj&YQ)*u1RIi5*Z|Ug$N4);wueSoMazSC-#c1^o&JfKFBkYGUbaZUK_+t4Kq=tn@PMW4P-?#mVVI=aOFvjn)mBq-nO6*1Y-QM z?DnC7>WT~kM@q&JG%7Oj+=U5H&rI%4%-V%Hx0v0zEsUaZWAbd`Pc&a)yX%R+NHx?U z1?ym)HA$6SmDObyca))T)vWDew_rGn%Cm78opmg-T9Rw2FO<1e=}^8>v}-OZ=UT%w z;m9}ycWtraFrBW)b*M30K@(D=$<|%WInoqpzFEmTOjXU^o4|lua~$O$$N-nnA|i1yr6YHxKNW*qst@08TRtM3xM z^f;AEtuOu#-@LT%)TvdUzn2C|Yx5J&A^YJMg<)ss%$3S;qdWnQN9|duhLZ70>n^jI z{87=Ckhd_Uvm03gPHILDk6|ZQORGZcm3;T2x@js$ZZ$>4gHF6Nj*rw+aN-7^d=D`w z^%H#fg5F^R`U5h8t&>=RU5u?M{D}mFkR4Z zbx<(cC=;U+TTrTT#R!#0dHS#(kVSzmuRnhH!vabZ(7yrZUIIz#s}7Go6{?23HVF## z`r|NH>E!iA>PhQk%caVbmZrTcCO39Z_S%5GS_lOIHBY1!aZNC8-YC}Exyj94aK%P5 zzDrTX4s!F|ye5wp6#{dj?+PK3TH^F*ts>E9k1hp%baC2C_0%YUP9viN>EQ~_2c>HU z3{?8C+Jqx1*53UM!+W*q^I}Ha>1{lB2IHpiz7^LN`Pq8W$^8?A3zNmx?Wh5K#s)m$ zA9F{M^J>4JkS2r*$eYo`frVAhsOVp@@@8SvUlQm1EIpy9! zwJV_Dm4kt&i_l&20*LccNlF!XzNbxQ!RwgAYRJHO4Bc!omDx>VR?TxwIHr^qS6Cs;KJHhjb2Ek>l)>@-l7&qRE2L|H%28X>`r(Fm zs9z`eSLG8&&UwtyInD$4JCpJ`Z4$RL*8Plcu})5tJd>P_BZ zq=aOJbO{vfqa~whZS2Nr&@;=N3$@TV;=Ih2qpbUxE3GGJydr?Uqp4ZE3@YiA47M&D zi(_-xC5E2=vR)}_CP9!bdH^9Rp9oNPEuw9v7JHfLusGA2i`>r)G&sksDt&-8>EmKK zcA-9O>9-CT63SPcNTzuXm12%N>z)$j2@DcB)iGLk0c#EFN$={4sX=Y>TF%0$x!x+laocq`#0PHut9WTM1s8y=zM| ziR)k*nsYN`QaaUouIa|Mt_W~gg7RX_GvhcJ0OG9cxSAxYGMNrA@f{|M1Ro3QO8UT` zr?+=rENua8wJqc2^ReE{Rw12Y3|4cFG!h&f;JP zA;xWMDcve=EO}%owC={uMJr_VyL07dF~O- zmP^+o8?A|0&Uy=}+q&;*9lw+xT!QX{iay6I(%FcQ0o9c}$c}1D{n`7u9A^N84lE0N z)~4dEcv?T)1R0JHT7so2QddjPwNa)rSZA*Pjm-v0z>}BO)My7}fUC;YlxQM31^x4aUPYXY24o`R2jOptJMh`^k_0A)E zLHe>Dr-e4S`^0g6<^kQPiv771U%=A_yH}E8H8rDDN*9dZTc>IK4T|n1(1-t&+h8E- z8EiY|7dU))S;g!DEm-?ua)>d?t4j>okI12O@}n0-gTmptDf}LGjBEBa3xhSwTI^~g zY{t1?B#L+3yE*p?*#QF}gZ2Rr&_i2DaBk0)TVD27j<)w z<_!ScfpxU z4qR;45ZjF@#Ms(~Hp7525sY#WNVs|dBR;P}tf-*#X{i_Sap*b`7JGD9E2 z$&7~BTUhSA^;Cf4<*+v<_|Csqek?6P7sZSeSAC$(_pRe{1T}6u{uD39o7Pm+BHRRY zZLP2r`+TBoEor}p$g{QD@cfoKjzZHbTJx9IPxt+jgwd?w~)vn}!&~yAlCqUii)2!~_)Vq!9VSdPi zsP7Bnx*i=EMhpZLVFUpq=tTShRg{nzX+NKSbaoL2R}?nVQduP>8E25#BmjaE4}RDV z&9m5;V?T;(&5-fhL-Pn_Y&`lDEapt#W#~wB7GS`2q5c82zJ+KA* zG2*({@Z{^YtD*oT9?gId2Pq!>=u>E*3P1KGeb%BW4V>dIYoKfe{qo+5uE< ztK!okAQ4<{)LpcDJn*@`{|O}fb}PZqTesph5j+R2M_1k+E(Z~b@3i|6r9Bk!`l)^C z2^3Q=@tPEqUP9fqhS9wx|9ok?XuznlyD2$(;pdN_x`Ex_{&=A$wHy3eGvR%nR-`ml z%tm1acv7w>(}{!v7mG%o)dmtvi{_dg0kN2DzweZZ5Mr=|a0E^L)*>-$jR|lhg2uk~ zenTu7oqG6mK%U>T&-L%oiBl(O)#@Sg6DbB!!^MtPMUarp>D5w!pO^N&P2+r1z$7&w$zTGzc+`W34pt!LiBsoj13-!0)JBs= z<&rEf8`)flDDcE#uvD6JAlAU}tl*a*C#qg+YHjPMN{Z$M42Tm+WbCo1L1I^lQ*UY@0y~tP2|tHCy)GEa=}IcuEEt@{9_qm+91qV>(9-oG8KE!3 zL0fCu-!skMjI~48NH)#13c@uaLBSBJV56j#%)-?&6lI#4UZE(9OF~miZ)6&^+;8xQ z9#DJ}U7!_7j$=?#9U@3C7c!1xDXPiAtEb-&cE(%O3C_)=+BLL>5I6(r1l?SdfR-rreI4 z9?sSl<%I9PXwoR?k-K}fSZO4S)yE!lF9WfdLkp*!&T7EsMBo)LKNWr>x3%3P6Y zFe~q;{6AQGr@&0NbxpJ?X2nh_72CFL+qSKWZQHhO+qP}HGqLwMdv~w7`t<3W{1>_V z#yeh(2LoiJn*GLt<;gCReian>sBpEdVeQ2kKcj5}eG&{*IY)oZqi*?Gfv9OQ4%2IS z-g|H)EML~r^%@=e9mvrH*dQS^W$DVYn_fesZOVUfspZ`vHxsfXsQ^hkd@o0yGD0qQ z8NNUV3jIKjqwEZo9m>J!T+-Kk>QUD%A=ul4w4OOTg-^+0nWay_o+LUR0|Ktj6<&V( zDOMZG$xPP*fKlfP`fsBBmDd=^&EzuuR@ZDuorBo;#tyFJhJ+sL#lrMwqmjHGnr_e*KPRJ-Ex;m?IWP}sj;+!tiW_zuQ)sl5SiE$QDfTzatRx7^j)Rp2 zGeT^DQzkZ#!6cZp&ZqkyWbQ`G<%~?@y)NeSa4${Niw1WE!(inPHyI1xf=`UN6v69!Bm zkyb9w8j+MuD3PbnSJ{DaI)$3J!9)yPSG_M4%H1Es789dlm@+HCH9fxxVjx(#J?r5x&t z1f8f+;xdw%qMR*0Rh676MVs4%oYBGZlD@KIP0MS4s9*HyD&It_#rDHS(kHC>@fLR~ zuM8beYQp$;t*rM5U~t0%+UV1lpb9@g7O^f~XwnJl2B;8|v3|F0jlB|k?t`NcP!xz~ zUdr!uD<;XvwFJ5y#DbaYH zJw9I$hM#j~UhXLU&c!c^*Nf6@NZc4HJb|^rc(7g@*UFZ-zHLTvI390pZs8tNP;3wJ zDPAZ0;ypAvBjgaIM(R#l;9QpHo$*C&`YZw=^BgFvsVH!S2#m*CJA`+aH3A<;9t?+}?SOjhO&47||;P7Hk2GGT<|+}KN6%1v=ny~&uBU2t{$5kUrPHWIhWB^jedYQof`6pdnT&ywu5N-Lj165S>+*2--U2wgI=JF|8FSKg3vUP5w zF(#)(adQ}M9B;Z?HABc6HGP-zwS@6KFa4R(&3zgFk6Wq!3citucpt{r>dgQRiZrN_ykT#L4s0;@vNX0 zHXxs4W`*I1wz;8S0q@kLfqW2~Ko|uO+0eDOW;dTOq>TjFDJ&0wx3zyW`1le)=eDC- z(Nxwva?oNAWNW*)>7hs=H~G2!EILjH(5Xm|RYXdpS~4g@7a{>rg3G4OZs09r{@|J> z+~VK7V`ICopG|*r(2QPbhNu>lE&SdNwH!mQ$T4Tn)!X5#h(eQuA;Q8vxj0kVeuPJf zbY}=O7%awe(fxYPzdUqF?15*EHnBr%uJ>!%>Idb|v<3vz=x{*}8PE%&`|pGUzI#p~ zX_C9h?7YK~G6&QSZYe7qJn0#EVMaD68M&F6M&juQn~==DC`Nf|V-c*kUVpT5RjQL^ za^T;-aiaZG3(o&5vbcAdrK(TNmby=+b1;54x5FEXzeg@km%d%5@mP4 zD;&!lySekyT~+^95e{EH6S9)eAa1bpCVD)7Ae28|Jn^dG5JL(eNMmkbO!k^wFuNF$ zH$4h&kOARBb`WS!5xEyxi({T4)F6ii?#~!o{28>&ftwWKx!7V!eck7LuyRJGH~b_O zKAXe#Sq=IjLC%jvWbT@!~y2WZOlws~tB)f|ebK zSDshH6A4*5?lRTJtxES>r`}^^^O}0Q1e0QjaSVV)mtWJ+0cesjd9PX0PPkvSPYA-33`QEOI+GC`uJ&ACpA)n}EZ(e>VI=ueN z7{Ql*5SxSA8Hgj&tS?~VhpZw=ZkR#J z5TNZRggc^jd|QyYx4FY5!qV#l3gV_GzsVwmZ^W zZeQ#jXfB!00nTRX<-WV^m)*(7%lkX%Z=xcqo}K{zRmNj1jMS!9Fu+IgHKyyXK4d`D zw1zlbivjjg{sCzg_M4h!@Gfjyy z?2({6(N8)ZY1r2-Q3Ww6Lh?qtwg;f=a&V?2YnJJOxYN-w$-#k83zn!tv@=v_Bbx8f z4*4R=0j7bduf04=1d0OhA9JWUXpU{Av8tH}(&^Qx;^+?^oUkC%+PIyh z7%s0S3Ki7qy|mn_{SfD6F={yF(-N%_465a^w@?IolLshOnMDhto6??c-yh&WShQrC zyLt|N+yfK%rP7jrneUI70HFSHg@+xxHZTK>oI;`=`ium7?O&X*pQ z1mJ-!6Vyk--tHQH`tGd5%*S5r*9-rn4+ho9ZIEDe%rJ@J$qe&LJ!FI#Lmo;U%5mmc zKEIVzBQvFmQZbOtY%tT^qQkUeKh{n+rT0YCW z?5AbW3@b1(N{H^3#w7 z!SWGhU`BYnLhW6!iECnC%x`K%fZip!`o?d16F*a;2gjLH_=Bhr#9NwAp`LXc=>E49 zV2L3fHQa%Vch z%A?06d$_-JS+11Ii6MNB1jXsSb<5nKFnj|1n!Ky9P5o)8`BrkClq-b))MmMsi?y683ju5A?je=x)+`F?!XF=3H~+d-1XbZ!C(C&&P@Px^m9RCkc8b1B zGU(8y?wkVp;ACTGz+*|h_VuA0s`Y&t@K@x01&abaRuhTvI$3p(^H)j9QX8rfKl)vlwf4My6ie65$`iP!0juNT<77NoXh!nU>^}boS zJB%PR4p2v^HPBdFk@Oy`9Z3W<5)QYiMOpytmVk~CFOAqEyB@I(t1D1$gd9Ydk*^!C zdmD!vkBnZQw>vQ3P`Z%9^jN)<@i)4V&}t!claNzOAu6`%fEQ(8SDW$W5kYAJT+o>G z$%mRqb`yMbbUf9@2x!PjQG3#X5MObYQ_(pIP^F6dSz@%fXgM`6HTuz1P8?(1dJM3jNY3S0 z9y4(HOp`W}wzDVHw6{rNrmF?BYrVnPC9*jBzJi(eYDWxOn8B3luWmA=>%RV`#!G9G zXNAYz=MQ%Y1R~cVedT)NA~f~2aF$r#;B^DBK9I4yiehF-rS-56k_?U1hy0Hys|;_O!` zuWv2dzsOv?gW*oLJu}T5Z~cm-=dtydqIb8!wZcTh_xZuop0c3ey%NqaeeVezPJJ8BP62O3BKQ z-(Hk35}C|%@4RnZe9FB6R_m0sT1C-9xM8TKe?v;g2pwx8sbN*+nE&cTVr&}gp&sUe z=1L{LZq>-sqi7;>&V3NR)3Pg5jsa3wPcUhBTW~hCwIKIW~lep-SP2L#Gv0BPY zaZa5e4O%Z>$xrUifjR%N@GSRRn#OQx4aY!X(*CrYS^uGL*NJbk$*YwBMKfj93{ZEO5-FHaZ}^CO<^tkY|8?t-b>^cAYS4 z&LN-soUKZ3I+#tDQx(~Tw};K3$MDJbq|m1(V7wfrC8B-lc9V*eU zKmUEK_?!Kw_?L=4R*d~@l{85sh;)PcnSxJI5ec&Bis-L6v23s%gVtqyF{V}>C%*6Z z-PhetgD9DpU-J1czp2Xc=&p{!KK(v}cQ4H;C3r~FWEMo9xA;)oFTTD zJ4CjA6(A&an*(6)sspH`No@hxLQs+>iE($^V|9ll%I=(nLCW_m+gYK=uKVaZlfgKjfI@5WzQE>o6It? zm+~I)J6Whbz8fso-g4eMw5E*+Pbi2uE;eCOqAh~k?`%ti?e!pXGarH< zMV$f+%Y1z!fLA7%%M2jIq`*fwt64Rb(G?+yY2Ys5Ok7o7MwKiP(6xz?Hl4_6kjgcm z4%a|k5zp?V;z$5#eMUN0SGbYLy$gvm5jR*+L%j}2oX z><_x|c@@=Qj2_lI=Mz)x@326wHCv3C^iz)}vKUM{rddH@Ef(AugM{M6d+?~3#?N4+ zy=Yd!-EWw&`C`0chZAJ=+~NF@QCziEL;KQIX+%1`#KH`CaTfmv3=jyN<@|(MdJ#iu z%oji>j(Ml<>TUF~(zM8(!ukcN5<)V4TqUUl@2$;Su5!i?6H$O}$T93qqZe;I;Nv0vd`{snCNr^?IE zz|VB?PxbmTHXsHn&{^PELERc_al<+>;dP>80FY-D2iO}F?>9_sueaz$b|A}4{oT)onzn22y9z0#n(+~FhA93nTz z$G34yH`*=H>uruS-&RS<>mw_(+8!v!w@d2+K|BDk}|XbWe(M{P@A+rK2Zh z+LW;J>`yd~N?j!ky<8N2aPP_I20Zo7{t4^%@2$P}MrXx(S5d@wy5M-I1{r`&;WS|g zfvs_Fkb_SGt}trgTQ(P-ft<2du`e`x>A&v9gxmQ-z~-al=31Sp`fP!Tt~otKP5|A7 zOX1jg(GkL=aXANvxHsWmPVy76<}kA&1dmD5b{=o=sZwjhj8c}zXj5*-2nUr9t~e-Z za>>FBGte}Q$eD`1s~XZx5gA#(e`6=83^cPmlRC5F?o9lRF!kLhBjPSgzUg;gjnW^Bto2&bLiW@sC#76pd@ZW&&d_ElIoKS?i+ z)>K0YcSh=m^R%GO_BW~}x-kvd@5dCkf3nN?CSw(dzJxTx{*hfK`M;f+6)g1)3{5Qm zU+mex8^nJ-0|+1j^Vs7NqGzL?{_G79o};(qe&9pPDzFzO35nbf>GOx#;zPSc1cH}g zY8XytGdl3JEAaSq_5if@_GQi)A|57Po{jnvw}EY~(^##f)`vI%^x6yPU9XUNVVLEB_Til`uOp7C-xS($~Dt#Ucd*W~#vNjW~G*g~i-p$RXvF=L( z5qkigL8`E_Z`v2TTyAn&&EeZ}yf-Um)M!Rm)7@H~p`bJNpuxPcwBBnBf_e$r5|hk5 z9411dY?7GEVdozyTkDP@ds{-U9E~;#PAR`|d2zb20~Y-SA|WCx60-f$$qB{h8f|~E z0|xifegf`W+$*wZtjH6j`Kut2P@78LAC_obQp5ZgoPB>)FvW>VA?wdFEO;vHsu;Qj z=;~g2Q`cj2pDBQZ%oV#NM&Dvn47NHmZw|sOk>3*KA*de|Il2@=|LW)N{8sE`2pFKrTw6?)!K2x86Opti(6 zgF--ah)HGNJCcVl&J1nuo}LCfl3gwzUpqG6J*_fVIuB*O-S*9W>uJ*H#)7zj`om%9 zN%tFMl|Z+~cj6`407Z9^A5NpkRAfsfTR)#YDlso&dzJRAy?*xs?mNS3#apfJT}iVv z?CJosA)ejka{V@0A}DlxrTLZVhX0)9QyISt$4+YW@KP=1$&TE$cn$shFmB5pL9}<3 zm-d>F_Ug!z(c^^Z&h-0o`&G6A`{}yQ$0+aDq zv;g52#bYnl^hmR=c+KX_=~Il?(;2gP>);mQ*Y)l}uF+k6#wAqgqNXAq{t4lRJ0=_g zQ3MgcTxP5V#R_X|Vl019VNXaco$$8_g<3`s)+t2mlj8uV9tI^BLN>-*!y1Ts3X#+_ zh;Ye;;=j}YC|IBfG4l7YaAbfr3eDhC6oSX7%10K)sH2nut6wK^hl?Zy;V%ZV-HWp~ zXVeu6B1D@vMC{B#2g@0S$R%!8Rb=U=`-T7@m=BE-{PZ4WWg@!Ql!z1pK43N16}J#K zfUh=B@76oo6*mKy-=X=wx#LV*K?P^MIH^Ilr6LJp0$bs@_tH{7rZO`vdn->Lql_`! zx8KNcJngniKRH9Qwu&MmxL}riRdZ365zK$z_I+g>xa1_bU?vq<_2e)DVf1@0t12x~ z)z;QD&^=qj5DET~@Ns&xJ!|}Q{nChp3X03=I-G-9vky=J--7KXKqu z>d^j-GD;FxPe<;-V4X8<%Jj?FTUCyi3u)q9GvchEDrv2(KqwlIeFk^F4z${bbqdDhR2g4 zw|Pw|Yuv8FE<#Oy9dCstH{8NtPF8ggsMt7+)S2YCFuW_aD!_i z5~n44pDQZgyPbua&L&-A=WPjdo`@eV6Dwy58LP(IM_)|N)rpM|SBiwC*@d3yMYQr~ zT^`XL8y~2M6yM)?1ZHcIGN^wkzE3Mt&OpiMxgdOKQR^pn z?Y2e=iwUW!?dY9{X8>D19)i*p-1E8g&KuF4BpfWq{CPgWITt@q&bL7oAi{ zN@K^OI#SE-a?*)tZXuNK%V%@yRZ$^!fw8J?329g*MTiPz-TD1IaPuWezf6~=Smq?W z<3W|PBmk?!Nx;WR@(m8>)TJWDD_M+)_GM7!JkrYUFnL$V_J%MQ4E*61qiaZ1*REdJgis;Yqh=Q%oy52ZCI&NV9K83IU2~} z0F)wH(=lEt?X4}ehqnFf7)gUyVRD<`C&y=%84Y*o?Tp{rGhJFu#PTVJ^UDJY=WSAb zkM`FELtCGuUHNZ0l~bhIF)$5pldH|g#7>0YwYFQ_M{vGZWmLgKkpTf%M0m{bFqO_g znQP)U`}u|seBA0F?tP1f<{B}y_E}$%l%Z`Q%oQ3&g`N|pg;;y_>hxr`jnga`h>o6k z^fjm!R!yvyqx{4fW&%RNnrnA|dzE4BysJzzYME!NKfiHZveeK>U}g4Pr_N~3)vzuI zuN%M+U~k580H4=9lJ;K+ul;z&HMwIAl%O3{A3=KxUjFscXxV8%k!IYIKm+IZzZ?7mCkzsu^G z4#Kp_jIjc&Weh92NcrTHLyqtGMTxKOe#TUY1w+~5<=hOultu8%Yw<+7S5h2|;eubG$b^U#a>Z}V0aB== zoVJZ*Q{T2Jj47GYQf*7WsaDd1iCUB?Ms+f^!kcTDLKK=XAlQ{9+t$w-Ev$Ww8|3pW z3aUB4bFS_-zpPs48^Ss>(cDn6NVxxRu#`EMZX>xUi9Tp;c*b2?S){)AZ$?}}Bu(ga zE)H#LQC*4EvBZajyf+Jfl$K=B^>jH zU8VtiP?t>jDanb(1vr7!8+qmh{Bp*uTdun9Da1@skAh=eMo`7>uJXE?YwUWaVBfL*2tg90}&;P)&?#UKsrshJI1t6+rcm^gz)C&ahJr~Dt< zAS3IVuZr3rjdUo{L)Dk`?Y4W`k{~H)$j}zCM_R9l6C}2DCN8vp-y>K=Ill%yf!RFV zbh(rbg(&Uz{upN0Ioo+)9yGHq?|1j<$BY^SWLC{W#G!`TCczu5ptCqs{U(qBmXpye zzc_sdRFEP)2u2URrHrDgoI`kU2tpkwQ5sl~Zl2VDeGixLN4P zP?x<7+1fnpOVgc7Ly|yG@=^uI?YZ`tF*ed%vxb zx{bp)YkNV}gwFY10RT}}HFprZ<7GISHuR+eL{6qXs|y`w*JW@;oV~Y3H2?sUu*WVJ z_qe^c1~VN#yH}+9p5bmC5%s*;U#3(sjl|n*OT82s2%K%d)SX3~i}d_qbHtkjnwbUV zk>|;`!)qF2Y!uOGceVYsIm^hyM@MFw5M$4S&ho!12C^<_W{u*UpCg~S8HQgf zin;SGa%)PD3k=)arP2}W`-GD0esEU!y+hyYm9S@aovgKc#WC^AA-pMaQMgz`2 zZSchZ?VR`@1H_+-x+Z#ZCYDC#2KH8#|GCKfFM~w6;;R#;0h%Y_vOQy}$&4kHh{6&4 zYLYqQavZL7({9C4 zmJf`NBbE=)kV&@MW%HPPij(Eq&HML^OP9*cxARRab&#n*Gn%#FYe9F^L0$6*v0D?9 zpD_n?GwfwMwKV)RKff#x7xR;Ya8Y_S_w=Z#(FAZpiiyRSS+jTaq10$LfFNf9ESS1^ zs=*_>EPOzkuZS7y$6UG;bT zqHjSFjWbM8$a|g6aN3Kq2;xYd3*rv|fEmx|EM_+=vpQ-|iK}TPH(*(283V*-5dz%! zGpnF@oNQYhFj`X#`v6-p6)l(p4hF~>CD_GdCRtFA8u&FIpJIJjQH6J5sX4%amkzDh@ zYrKPK2>5C$M)hCAjWBACxU99^730bd0tnF1aHa4L27ae*_J(tXP zsilZaFg(1>q$DX};`l>LE8Qw>wu

kv_c~Q}~#ZPlm)VWmb#c;E5H-Bxx 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 P-@rd8K)6GNTh#vna6KmO literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar.sha1 new file mode 100644 index 000000000000..686c680774ce --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar.sha1 @@ -0,0 +1 @@ +60783e4623f2e44063cf2d43d9fbacb2816855c2 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom new file mode 100644 index 000000000000..4c608288267d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom @@ -0,0 +1,235 @@ + + 4.0.0 + org.codehaus.plexus + plexus-utils + Plexus Common Utilities + 1.0.4 + + + + +

dev@plexus.codehaus.org
+ + + + irc + + 6667 + #plexus + irc.codehaus.org + + + + + 2001 + + + Plexus Developer List + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/pipermail/plexus-dev/ + + + + + jvanzyl + Jason van Zyl + jason@zenplex.com + Zenplex + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + trygvis + Trygve Laugstol + trygvis@codehaus.org + + Developer + + + + kenney + Kenney Westerhof + kenney@codehaus.org + + Developer + + + + + scm:svn:svn://svn.codehaus.org/plexus/scm/trunk/plexus-utils + scm:svn:https://svn.codehaus.org/plexus/trunk/plexus-utils + + + Codehaus + http://www.codehaus.org/ + + + src/main/java + src/main/scripts + src/test/java + target/classes + target/test-classes + + + src/main/resources + + + + + src/test/resources + + + target + + + maven-release-plugin + 2.0-beta-3-SNAPSHOT + + https://svn.codehaus.org/plexus/tags + + + + maven-surefire-plugin + RELEASE + + + org/codehaus/plexus/util/FileBasedTestCase.java + **/Test*.java + + + + + + + + + false + + snapshots + Maven Snapshot Development Repository + http://snapshots.maven.codehaus.org/maven2 + + + + false + + central + Maven Repository Switchboard + http://repo1.maven.org/maven2 + + + + + + false + + snapshots-plugins + Maven Snapshot Plugins Development Repository + http://snapshots.maven.codehaus.org/maven2 + + + + false + + central + Maven Plugin Repository + http://repo1.maven.org/maven2 + + + + + junit + junit + 3.8.1 + test + + + + target/site + + + + repo1 + Maven Central Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/to-ibiblio/maven2 + + + snapshots + Maven Central Development Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/snapshots/maven2 + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom.sha1 new file mode 100644 index 000000000000..f74d077845a5 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom.sha1 @@ -0,0 +1 @@ +a82e1ddd2d795616ac58d73ed246b8ec65326dfa /home/projects/maven/repository-staging/to-ibiblio/maven2/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.pom diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..5c50e1779f7ed95c94394c5ad401580fb09a6f53 GIT binary patch literal 168568 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⪼m1!ESbf=Jzf>1l~;9J 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 I2?Xx{0D7eyEdT%j literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.md5 new file mode 100644 index 000000000000..a7ca769a03a0 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.md5 @@ -0,0 +1 @@ +49e112a6c1ad24962643ef9494f9cbe1 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.sha1 new file mode 100644 index 000000000000..28f6dbb585ab --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.jar.sha1 @@ -0,0 +1 @@ +fa632b7f1cb7c50963d0fb7d818ca93c75c10127 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom new file mode 100644 index 000000000000..6cf9079989bf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom @@ -0,0 +1,27 @@ + + + plexus + org.codehaus.plexus + 1.0.4 + + 4.0.0 + plexus-utils + Plexus Common Utilities + 1.1 + + + + maven-surefire-plugin + + + org/codehaus/plexus/util/FileBasedTestCase.java + **/Test*.java + + + + + + + deployed + + \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.md5 new file mode 100644 index 000000000000..6de9bf4794f2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.md5 @@ -0,0 +1 @@ +6e902bab552ae52fef5875d27c4cf0a0 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.sha1 new file mode 100644 index 000000000000..4dc64d4ae8c9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.1/plexus-utils-1.1.pom.sha1 @@ -0,0 +1 @@ +15492ecd00920daca9ec15f6acd695b626621e5b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar new file mode 100644 index 0000000000000000000000000000000000000000..449afb9c1fe3ecdf56ec7e68792a8c9c9a3deaae GIT binary patch literal 205043 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 z%0D=;=g?>H->#63c|%qLDSd(gAM79E2Wiv}#&{sVh~FY>ovKt~Zp?TU;tDWRt{0+W(1Qk1>U>L@h5G&o4Wv_AT&Ct#7lDTq z1z?{MRp!FVMX4Y;FzJ^R6W75H1sDTiN|VN&v*D!p^GRITCDZ9mUd)Ao;RfYLgXhOd z&{1&$3|@5P^?Ka^z|>Ce-?gcgC;w@(#hB;N+y-1P=93*)?ldqKUXABZe(t;1)mOb> zxjUCnHXK_6f8w4JoeQJDHfV3#43Zb$2Ev9T!-mvT`_UDL53T|UX>`Px9qCtL!#k-9 zuk(`)5VfYFF-e{adrfx#H7$n(BQO49CdkG-C#I4H#b;Wua}FL`-GVSA5r&%WNcu?h zS7a8-wB9F=B%C7AL{c%A#>M;%)6!05!lF-36jHsD#av>r;MbAq>%2bMWV}9pKPQn5 zQYAM;A@=75AO+dFS#om0XUsX6FS>D3{@mSoED;T00-DQ5{Lqj$-xcO zkTs;eE0;zUVsSmpaUBlSS~^1lt01FQ2vS$<;9n6mXOCBs&^t*bF%}{;h*gl3$@kJR z^FBpml@zK%xTN_Gqm+37aWQyejf8m-%0gg;FIrI+pmbs|>EUhKf=2}rbRn=!7)@(v z7*ljXzQ1r$`s#h=uB31Gd}z1GYpQgJvd(8YXJO_A#0B>jB1xe;HlgKzlteUd7*yxy zs4HZ20Ip28oT0V8tLYp}IP0a{43`PmG=Of9jUK%8t?k|#i3e=mq8!@JMt{3<6vrYX z>9k5jG7L~GCY}346>S|bD(IyXiL9{`&x;jlV+ec->?S+ieond|8Glz)+GjDGdgwtd0X^yAeG z>e)ioyX1Xa3(VsB=Whf_&-=!R17;`yKdw{YoX-I;ubD5U`x9CwN+66C;0@K;Zf*x! z!`u`TYz;FQ5=?W}1tv#4xgu;$Ox#sNc`1+{b1d8ml<6B4+XA+(9r*P=*#!z%?@%QY#|jZn*wFQ)DpSy@gn=o* zXkyV^94at-{i{+2U#RR+DkO>?wPSIq`;16eoKM9Q7k-urCk7xo76cw26pcO@unQ;T zpw97E6Hr!%d z$a&nfSsspQyAw5!{Po(xY&dP=IwTYC90GVTI5j0gUe~=R`5&KtS3^v4`7O8|B!fwg z$qS9*3<<;wbH8?BL^0#s4d7Cl6$YkUslgv>cN5Xp3*Htek-2XYFDwm0D16x7GjAM|+u{Of>f5)A2wfHU`}Iqb?4Bj}azgKQLD z1_l|DpF-p^mzbz1cG{%02xp>{i}Mp{+%;$F+~Z4EgZ#E}vPOmP)vy0nRPR>&3BGNL zZdUS~nbE6ZHqQet0xaAx4jS}*yGP_aF5t*Qn4`NGJxc z#>%8YS2FjmDF???1EoOaNvGMmMr@flHI@`SKjvH^EOow6apIk!6c{g-*8UTJrdL%u z0l=+aLVjwcK!(j#bPj1tO7F27HWk#vMuqJt^03^yvo$Kn@M(|4qJki3T@KhuBnV9; z6gJ6e6zIy3k@BQ0D&$q6m3wMO4{B?4H!UEuLjXV%qWTo*!toEdNqff%;fw7mZVA=rOm7HzA=(ymt)? zpmr3mkTzKn{pAp(I|MPWam=2Wi3nJV7Y=Ll%Lc9;9MuPN16cKS#1on84}7YlnBl-U zfz8)sMX{_DA*}2>aC-bF38j@@y6q7*G~oRMS#07SP@l(`Zgs8@V~vm!LM=el(wiC& zChaZfzLvleE@v3e@*P#dsL8j(LkY@z+_X$AogTug2lzbEYUn;y8+@;~q@lHK%s z9_W^+e1k+M!0UAWAXh1U0ZmVg)`|V0t{T4Q!f`urFMJ436rQqY3BD?DH-)^nPIym` zeU>CPg%gpr!1}C`8FGQishGQ$^Ocpn(cG?c)#|@ifs9IOphN`BI5Ntm4$rxYSC@9& z>~U>R>FDZq`!fU-U!G*Fj#4(gjgWI=ji0bqLvHh(PhF}30vv}7+?D}|w;bSONoHKR zu26H*$KgUCqX^zFSphGn_Gl2S1yH$UF!$43Xugnus4OI?Koiz^9{ghoxmA-gkZl>f z*nQu3|G<-e5T(Tk+bDi&wB9CVI?k;rFk}zs*0Ahql*Y>0J>ObPTJvx!){z+*hzA+1o?wR3d<0q}5&{NqWnx8w`5h#;e#5U-%2M>ggZznF@+hx)-HgO^ zCXTtdz^KcX8)hu}S>QJ|4E6N2NQ_&bK9_=&Nq%R}kpKB#KIa)&mjy8@RT>Y_qE3R* z(iE!gx_WFjR(;8gQrVTqCngz5^8L#O9`6I)xm~>SX%4m}y1s3(9RJWX`C?GR(iqK4 zXp#k(&Ka=}*ll~);+w_zFsbY^hTmMQ@TdJiEPbeVNL^sHhudgAC{PM-wB|qB8mht! z0ycp_tT2U36jLgP6lc+OKO!S&Sg zRBHphmazAHp2^%Xa`Ba0`xh^+?-D%GyGnLoYb!hV>N>fPqZ;0|}!f9)yc_2tJk0e4&3XE0P z<+y}Vy^{vX{7@>^xY!iL{z$Fg)*+26z-J{UfRw`vg>=j&lWJLDtzK%V2z9BO?nPcZ z`7-RxpcTsCRHG9=6ZTSkbZKDbZh{uObJOdF*!M&cp)5&XA+rmvQ&=|WL#Ea8g}i$L ziIvIsn?GCJRn8hx{6W09<}6e9>Mfs2R7^elwN+YsU7RZ{^`4t_y2F$?f*8~VZ-Ty- zged!_Q;$30NRQ&3Io;0q1m?qTjL`b%r9TPKRt8QsSJBOSK=rO$s$bkOcJ3D5Q}7PW z^0*ooxynd@C#L?*I;FNN9Xom(3a9>z;l!2xIc%?)Vf*PRPECDe zHvZceA693JluLg19JS`HrqCzk=r>%+JE?K`FG1huT?T}}X@`tX{V{ps30Sy=KS&la zflc6al47J2GSko@rvBw7{>3K3Eh&dW@q-b6^VZS?`pbTm9%jO_MHKAFWhCmaC@g3b zIqJoOkXN^}xWE#V>WX=1C`F0=DHa}4KDzav?Ch&r`mGgxw$e2zbpu!p0-Ml}i69Uv z4T3W7I`?}_f$zu)ltGC)2+0N`s|q$$x%to_hYbtOe0VPJ&pu2w4A6$V`3hB@C^k4@ zR;+m(Dfft11G8oSkY7MR$lLW-WCR)O(mAM2-EhcLQoU^3j~Wv- znhTdaQ+y+?4KER{Tl=pft;0LlVK$Aq(U;mHx?|Pyn)1EQb~ny}>257L{)q1gv{bcV z!wlf`4N8Ry)j^VKxDt!fejyt|nng73W25rHC!thydU>PU)8D!}-0Y+^7G?q=Eku+x zsITExryK|CM8nMMCR3|xGq)l&RAFImgGY(@0gy@6{_zjnQrId>;2*$U_Aglab;^jsi4mrc%8Qw!B~gY{fs zJ(ru$R96etw}bSWal0?jo+@m9{uiik`|G)odoIs>BiC}pX45~8k9#LOZNCzfgBEV@ zsxtzOfHH{}rm&S8O@2$^=3o}ZaG5k@lqxM8(@!doCgKg{$7!A|#!d7^(T!0Qwd?DT zsG&YTY8lWUH=g;z7V$=531&0_m&K1N5XTmZxXZxEU<=ZMpG z0VrOJa$uj*FZrA#)t|G}E9KB)T~z3dyk` zd?hHcG+rua=xuD)>?BbdESwRY+mmfdQK}}$u{TEQQUZ}0H6p&p;kEf^0I?S|*$E+5 z#12fuPyl+P*c#NqDg?ZoW{U5tfyob|H2I4gV26g(5Zkr$cj1V0t?+@yzF;0%<__L( zpfl+HMKZPg)lR|+#b>sQxWcfR@6{swYMp7z*a5OA@s8#~)S09kf^s_Gp0s3=#?;o{ zv9)hWIFVs|MOdR?zNs8k^6KP0`@}KE3+EUcxMf5vFX$XB;!MUQWD+SF_MoDA?!T$z zfZ8#EJ=t%<*+v7NN{U%LpUfe3)Bejv<;7NBl=I~~vb!>7B&VRnz;5L`tox@P&1CEw z;`Ah35eq+nYaYRUCQZooC!2Iuuw<5Eyt@+I)pf8&>0W~h-|a8V`~2|sQ~6y^5NxIg z2Fs;|rF^k?`qlK~I}gT>H(m$x$vuyt{+k~Or6r%E?o*az3cJpyJhd^a-HpMOGqy-N z=k*;b;B8u~KPvO;trXXpR{@hV8R~cF^0B_xB`ewA#Y6PcBWZ_XPE~)Po#UCT_ar{jww8DS1dd|3T6eACL zU3ohJr>)R_$8Lw!Sd(E6%F4aEl~ftbtvKBp@!I=Japmm-l=u`@%AXprbHD7gmU|(0 ziURRb^j^riBoJIwc&EZSao_A?5*_a7V}*yE7Mg1;07rJjbR{MLUTpTy*@+w81X+8N zN6onj2m8RwEWGxi(Ci=^)Czt576ivfi2#srOusrlr+kh26>}+Cq;-tV#VsnhKdL-OED9 z^@;dKcz#r8Iq{KanMIa|4=ZRY!p7SoGkY0lO7@A}uQA1MXk1QDn!S~$GN-RpITtN1 zQP39q5Zfo`W0l93S1eZX6T7~0^Dz*R93YrCsbU#+1I_gSz@p-909jgF9;}l+1Im#gu)&0>eO%Z`Xp}J zsr$jB7ihEOtHWzE00MlX=UvnamV9v?U4-Tf_(F?a^aeYA+B6Ng?KyvXb0~iUWIV$Y z7Wjf(KF96@ecIKDe#6i$@{gL|gNjA?_Pag%8WnK>ZG#1p!@$X7W8pBtxc4*cpN63C zu+fxYuhUG98MKc8u*rSLW$VKrz1s8(I zlKLrNr72nCXQrW9F{bw8) zhTj;gm|>^P4>_t{!6quy)d5kYvYv9rj?v>Y|Bx)O;J4$)%RlxW<4t%FVdg3O}{?Z5UxtDJ1&Snqb zBLP@jzu+!L;!|uJ?jDYq%4wXTo#IoJ&=> zatw(O;vzA^#gga}gCMdvW)5JR1&3FN_>Sp*_K%<00EZDNR54^mG(i=smVV;=1&FfY zDc(9gpZFJ6>d6ZP@Xn`=KG?PcL+ti!4|PVE^tzsf5d8r& z6$o51FF1TEZ#yuaaWYlql7a?iF$$*Z{OnM!_;HT_>6|=VpS+|Gy%OVtQt=9CBJ!`x zvr@U2(+sJ>9Y&NN>;f=@%#BAoBJdobdoa_rl&*77xgVxZidhtTJjC$dMk((~|C+BJ z`BI^iQx$VO`NCh$f^=Y{r}L*C71F=4WPk561#>R6=Fzlae!}1F@*dbm@$#F-2c?rOjnkAS6FTL+boa4MK&fj5tU)=jLz*o>&1G0=&5b%D^a&;?K0|BiM5 z-LlpJZpB<3&>eB9!ybJ-d=tdEWv>YpkILKwAECX=s^9)It%90kuxm7_Fx9LuhNu6j z7>!;4g=hSiL2f8dKm;6kH3o@aV!1wTYY=ZBJ|gSN^zZuXaJa|Vy`S&`uzAr0@*{#* z8gD|vifbeA0}nUJ@M(a~yJ-U~lhnl3 zhiugamm|h)ucJ3168{JD4cOvZ;6OJzRPU`*eL{Cz)JfMS!w zH|Ov%1}Pr7&^q#+l|uwG2Tbi?X2t3EKaDbK0QYJ){VZ~mf&u^t{l6wiEo^_rM(ypa z4V*3PZ0SX9T@4(C44h1i|7EdT+0Mn$$mCy#9E+7N<&YH-zTjxBJFSaTA{`a)L#`b) zMFkK*@&y)(!s?ZfzicKYIgL9vuX5Pp-iY2&G9WN~-vIcM9A;Vy^ux(Y&Zn~0)9rdV znNK%g>3;!gtj!th<-~y8jE-Y1-UC>em>4p+L>UQ%OOlo()j9JF5yLKG;aQ~_oE_K> zz5s{#fB0|LRd=AoJTJUjZlwl*N5X_R;NAhb0TYS_GS}%&Xd%_aO~S-Gmy97ydwM+; zlhf;b73k4Ad^hVljwMcbnQT&S^eCLBFjKvPqUy|e`3zGjpY-U$S7i*sO9np&Q@8(m z#L$DFUm(HJvscX<{w(Rt>#CIJNUzA%=ffDyWQZ3MiVYiJtaams=rH}Ee;frgb z4`dg*VSZ}OtkRMR?LSEPypSfcO1fxDD$iD&MIYHS>Rz!SMT21K7pKU6^yr66PgmOi!iHku{o(Lx6 zypY%}*x+^j4A z1piD_U;Nw)f&cuS_~FI=pKnBVg03`>AWF!tX0xjLV%1a+3!xCK)>%VAULSR3~yD-EVCU>Gd{lE9l*4*l6V2eV2%}-q`Dd- z;n9*9+K^zxR-k>xBQ3YzL(_e!DIVjYqfIVEHs`raD3(rM&uqdU1Lu&*WHt_{TW&#K zliX+?P_(6!)ogCX4a8m6H2ocYrd)M7m2>uGQmv6LE^j=EaiOc*WOl_E7QvfT#4`!Udc@$&7U6Q4 zFeQtZ%XFrC(mA;(qfd6n%tC9=l);6(2l(C%#c^Rpn=z=lI z$1+np=B$3?XCyTq5%K!<*R3iA{blYD3!;9$59b7U%VrPn2D&P#42tKo_7{T2`(r#% z>{t8)j(qbWcl%%VGFA^UKzQ%M9r8pg!3K6$wUHSOHqq<_Vq8l6RF-2yc{u6!AlMiS zTp+;JhHtSL``}ju=q>D~7YlXwkZpQ|?d#dH-!zUHTl9q!-mt7y$m=DrI+?~sh|&TM zk5xDjI{5=ZkGKwa>svQILdEZ>%Z;fAQGyJtB-=EfWW2a3i?nB(PqYj@0hPfDkF5&G zv=LtUm!kgcKL6w)Q`-A|{_!=y`#CD&|M{b$;Ar==VBu_G;`DzxE(z;Wg90ca-{*!h zQ7*NAU5RZ#fp*uQDy zXW?T3aH_N@3aktKETEawSQ*Upclv+=Q7Z^gq@)oUlQK&`vbgJ0a-5b{TQR^|is_%} z2Ca|(CRk?XE5LUI7!*QXqL+IF3O^g(-DRlUh^ zUFCu+%SVyW^N|!q?uHIh$tv8B*^Lj}{+Iz{OV+|7N3y}dU}-eeN1=vv``$(yJT zlu-)|{NsC3mXM@>e?%h}J-9O%`>-=9|_v8SKzX^??Jw1;)ZXRGi}b=k@*;t~@lfnzF&EtB6|U7z}OP z@??o};+PGECenj8qGj=6BO@X-&;d$Rj3q%YHZIC{N{S@XLpOj>AY&z-45_Nh){pVK z=!x7YLYwU9K)hVUb*uH;$b>A2S?4xifugX?Lz=(%d8_yCwD%n8!&<1xTfP9 znwwIw9&2`CZg#6D>ChnQW0zEUcUBj;=3(-L?2=GAbKGFkaHBJNv{w;`vo665e)N0Y zA%6xNrE36*^$=iZ*6c7Nh2Le&Bz@juoGy-(nE=n^)C|OD0y2ydW=Vou_J~>MNvS_T z^p8N!$dq92Oi=UP4{JICvf<^D&wZcxGuJm=C^{-)3`zIFc7j`V^J zEM_^3%bt*9SiGJg)d6YDu29pYf#TEAz~cqMCGI-EJ^~P zX{FZ!HJ9a$8G*RwQWT}m>oCC*ngo86lP|mgf4fbb3Z;milmym*<-e!{vYHd(F4hlJ zYw}o=HK#v#PRxltNha-Du>hg^!37O_258&@uAoLm`28NvF8-lCzb{h?;FICj6gT~b z_r0VE;EPI9{8@YhH1Kr9RHP)Na>t{058F%;L7^tFB^@d$C9oZh0V=qI?WU43i`4?h z6Ck1!W_85dXM49q!FteO3p{q{z4%c<6y?bSdnn5pP`AvZicP-H!-BZeR2k05;8Bw$ ztcv*Ju{3DskXDyTR zsLB*N1YXL`d9>hdF92&-#)guUJ#5caJ!fBPb_&F_&JrB-!y+JOkKXd)+4!;vPev{) zt`By#S(7lZBV#if8l*dTCb*xA%;t#U7(Upmo0Zq#rTF3XAsuvRjT+1 z7vv$anXwIV@08k&3?e-Q+HOu{5PtFw-wr}2iQ*1w2PZQ4HKI3=!m(KF&NJY{h1#_Y zsCB=_M^ed~WQXm5Prr{KT8jBAkz7{~6X!*5`SYKo9$wUmu+x6r^~BG^@t=3w|64k% z8(j}KzyKpMTig^JUMoYvof^AHBct%&U?RjC&bzAW$w> zK@2NOXiQp235F2<$pFVz_J>;>sTi9sS5ZE7HBo98K5B_2s>xF4;QUx6s2O>v<-any zs_`o-)KFC`KQmNhH&|p(lS@sban z5sVnT>jE@F0*T}zFwh-TL`uL)<6wzG9rz!7wr+*{Lm`7R0@7zOD4jYLSx~URJNK))60@ekcndWYGa8FlI7hWtpAIR9fjXKb=wZfI-uZ3Ap2t z>8gO;sTdAR?`1xH)5T%N;Ee~1^*U#-U*9dCz`~CZgc=#KQm39gSlI#CKcv?TY zYHL=uspj*uh4xLj>{wwDn;J~=h(JebnOkt@$xx0>WCRu~51JZCSSGa`DT$r< zDK{D|MHrz?_IeYjOSqM|J55o@I-f9~SkSrN7`K?CJ+wzDHaV{QP!DDUEA*R43ZDS0 zYkYbSuL+QkRP&^+&9r3Wgbn9bMPXcVXEQw}*bRgd=|aI2>_y_9%aUz!aH>bht|$!_ zD_)3uqHeV-R@_9vjNu}uzCXygVh=B^?chW{$zY`;S-Hk$!c$af%=P3foRz`$=5rlf zTxT$8yN=r=cczxIUNBl#{NYnrup&`w>Sj+MbPAZ%jpL`Fch*7uA?liS8qx#G`hW43wY@djQ z`+$Qc8u2>16V&z-O}v>!;@ZkE+CsezW5~*E>wWgl06v1Bbes4z=~JUR(zKpYO!u_r z;f%+CUf=+`*L9sbebQZwBd}ZQen_a58;=7jRZYo$L}$r<%&$P#Gb*0NyOB*%XPH6t zSo6iZQEpR&G_g2t?Q)OxnHS;-jz$15;upou{@XFStpJn^MxiCL*~PUn`f)T39skW! z$HUPjeXAq-_;9l2c5B%Sr_BtNvh}xH=et`25Kib}FiefR@BvxcFvjNV5%ha0O7!=bXkXvEREiTaRG^&!qn4YVPq&PIRT@rs4FE%)Po!0b*JN>rz|cG zFP@7kpxazbP#p3e{>q+k23>uUxi{cI1C9oYms%_74e zs9o4|fqI?s*mc>ZblR7NCpqfE-#V~0hf%|DnbL*m4opGL|J{vyMwyS%+}7if+?Og<7VDxMVLyIr)&%R14xO zM7>HH{3IOTg&xr-nBR7mXadvKPc=rtS zAzNmVfb3ue^&ECaEdfa_w9DY-0Ru2z;jx*k^6fv9blo!v7K?wp_v6pQ{{Qjfj&@G= zKh>Fkl&6KQ4V;|*7yYK>C|Rfh287_`o2ylD6!KuvA-?OWqfPO|ZeHe~HdL1*;&5L4)XxhX=9AU1DVUYyJ$I~NPqO_Q% zK?8pxq}|k-&w%WrJ4)t7ZQ5GqJLjk{n;SpGHPJy3PQ0v=Z)2$tQt;W>2h={?Ef=8u zzadAc48Y%37$C=^8E(8&xa2tv5?ao&|6_$pvPQvG@u%!C`%{GE|8Kmxuz``eiL8Z_ z)4wL7*-HI#K#V9^bkNY$6a@tZ;zo0U!D(p-QRqm>$aBCUUYgh~rq>DEHT|;>#s~fI zcZE@Q=qz|$0-0Scx6?AaET12q-vE6MXGEbL(AX~EUT`m%P^nVXPQ!6lIX|98?~MSH z?Okee^T>jx(2Eg{LisW@2SSWU>D(i}DZ17$L`mMg2d6CUaXN1Ds^uK~+G zUidpv_#c)yW-X*bpqi%e0e33iLZNBq5doQ4pXLrYEExSZb2{3En-bG1&B*=VpiG)r zJ?4kfg*;$x7-aF}wW^lw55U}BD6<7oJWz0O7+lnUjmt`ucn~}XZbxE4jLqq{S%7~f z1fqR{VV~ETCm?%TlmDfNB8%hq4t&l?jzodhe83=$IOYVPqe>URQxz&cf>W&mP5+dy znFaJ6%Pdp$wwj-GMRPktQrIb=bE^*lTd@F**!_>z5`<|BGX1es?T_@9z<v zcE*ynrgr~kF6B+zMF9lfLk>p98`AE1uniQ7I1YtW?j$HeRRUEhV5NNcyC#?Ip=2ZN zmcWfKR3&W^yf=WJu+B7>vtTk&AnBd-_4I5fQ?r-FS$KRv4UM^cBeGbYnzJ9Uwi2~; zH4&>aoht6CgYb_&XH1+GrzEomIf_;0L3JI^K6};J`W?^20F9p#HncR~jx3gi4rxT6!JhH=-V!Nw(BnRP~6&sq)t}Grh*<@*ct5zD=$McaQSnG zcu%F;Eyz+~8iTSe>H)6C+_O5G0=s}0RXpbU7_Bf_!TI|w{@iU=dGMcLH~T&QfG}7T z`Vxb{!0?Q<{*ANWzAi!i#4WR{Y@7)STpJbO)Ha>#;rvzpag>u0qw<$Tf>s=oyxBSN zj>W4VC>(pk;fM!wdcrLBhLLfngWwYK6WiyVjVfPkrz`wB_$P0I=N}I$U+s!<_^%Yn zTlp%EiSDXz_#+Syg;lI;Dcq!wykkYY6s9it>AYo1rax1l>vKEB;G^!eMBsB~Wlx|U z?-4-WgCO3cD4%_tFR?BQ1~{k6b4pU78l8TUFOqXEC6t9F(-rNL5}jk$hfzahkTOWB zpTI6Knrf&pRG3jzR1s2Wq@->z4(|vKSjtgSG{-IobPeB18Rtxm;J=Vtp&Qc#?*FO$ z#jH&gQ2moX#9;scu>RN2@V_41YW060PEfz>9!$xYc_bhp8R8H%Vbg;opeP_kB-R2* z@&qkFiW0}AnT!)KO%>-m0$ZAwZCeVGwJMafD*y?@iGF~a9k=GoTB$2))ys!V?z}PWUi4XP@AuTM zoDadB?N7o)eCZX6EfFkd_B%O%!@R8((iY|%=T`Fqw zoeUh}(exqH@thAR)A3XTfOeM@4u+|Q0^heGs^2YPg|A2`%ZfXR^y}h6v|u&ow^^&u zSLwC53){$gcMA?b@*Hmfsw0SlQ-9$wDI{_8%3y4dfPmDzK4C;zA;Bb8Z4vzO`lV#k(Ua_?_gHj%A z;h3`W0Ds+H;X{Wq8Lcp~xri!bqhCUlQlUCR#dG<5Vn%JUoJhe=!gHI}wgKZLnYsL%~2yFhXN(2h&VKJpOj@7$BzNtgOLf%u|X(8^Ugm>+f3F zduyW$>C1uu-4xjje3tEcTRvi{g@@vd_GqeEL?72UFTsKdM-sKs)1RP8@#WOAsS%A0 z1HzkO4HFtbsiPY9%?d?#$xw^Y>sog>xCw0Ya$Hiu48@<}^)A3r77YV{3`N`zv5AvB zHKoh#_dSZ|(nYntWj)l!>UK6Cr$)exU}XTu0EP}0D8_?l$gx@ymCGn#2@?@o`h#Li zXFpn)*N*q3_NywJ_-M{m(qh7b8A4u;Hx?J#e=3CitMXt~!fcLWWM_!q?h^lQT(^91 zk%>knlXoy)hS+$S8;XumeC2V=7mBK>69Q zcu`7$$6Ro2K9hkCvst{Nj4wG7Fp?0LG__AjU^eE$by{vtj3VKitSzg1XW|%w> zE=()MB{z7^WvN(Nh)Rf?Xh#Ok3m;e5)aP7>GPYmv+tUw`>nNc^A9)fer>2RQxZTkTX$AG$M+L5|@KxzAq( z{9|B9D|96X1N$!BQT2tYC(T!3tKp6QJ^Sc*UMMkvp-f0@JE0 zhi}j)Rnc6VC8igAKD9nJ=KhwP@fn?(G7gs$p(*A_UM&NS3tfCt?o;P*KVAKqlR>eB z!>n(EB}1O4W2pO!93Ymvf?;i-K-W*N_3IUZJ}gr z8rv&LGr-=H!_KSQGun|DoqJyk4b2LV;*~kNZJ_$HbkWap#+@0F#5_tPoF2zn-=B)d zjr`%i=Xh3~yu#EBj2*!-6qjLFnDaAXb;P&BW0k_mW&hoydbkxvYu)aYr8LWMJUAiREE>$_>j2N=f|8%S6>NY>vD&qPch)+P&(*yVs4+pC+S>*_IN6+y zp?kxiIqrboz+69a*{0t1@UHAeG)m&mnkn50&zY^FPZUx93ZcC$wE;(UT%^^$CV&D& zA%NVjHJ(ahhHct_nHvC7&xtO*E;Q2z%5qACv1XZ}F}}#mh-7x?#F7M7%xG2EB!=wA z213aim<9HYW#LKZk#TMUOS`o?M#^=MYiQIt8&axOcilg>F(viuz8^PD_lg=h$TLp+ z=8g+)pTmFj@@#;Dv2E<~Oe|;BK(m`v`I_fJqIR*gfBLq0YyftwKYDDGmgUtoV>6uS zYJ_K@vTl{d3N3nk6mo>n{kDEU!8K#GtRKFz`Z=b90GCg&=^!ZagkE(j;I*4iE6i z+ZX-8>ea{@nB1s?v4zelCZ#rjCUZay*_?N1wu zM}X*#X?(1FJh|473Q?|p{HgZQ0E$P4XpU)oq)bCA z$*Ns^qcjb2gh{(7@lG(QF2(tDNF!s&F0jaf9@zLNMrY~r#nF{8~T0D*{MK8 z3KrP7zKXn!=n_Cw)04U#W^~bOn2PDv23*6$bYeQk;qu!l)Q_a+J?725JGXauyuK=} z?|!LYfh#KQxP=kke;F(NOPq~dKWB(hp)flLlPdOfNk#vC zLY0?5Xp|D`k}PveN(`ejLSQQpY;^3De2^0sA-6fAnwhO(_d5Y{OXDZg!-bIXhp$`q z_Ou%05C>e^;z%ihoir!t*=FfX02>bk0Xm1ks-n4p){;fYVAb2xV|#EZsP4i$G3S)D z&EKEry5SzCw-fSR2NZ7@h(GN8Z^<~ITpbF9fDREHyEA(I>}PJb)5(e8W*knq&;2-O zuE$=v9A;~IC(rQwWr<5U2ET`05 zIKsUim$g*NpFx)U9G3%m`tz7^!mV(17BOT&5A|{uU*D7k51Z~Mkkk48C zSNszt+EG#+QUZ~XjiXiD`m!WJdlo{pO@SJi%zzxh`nLimW!qAX_)cATHitNNCsds3 z)*isKv-K~p>8^=c9@XpIlPu5~6(YGlNuu_Bec-9QjHuKfH2w!;-xQu{l&zVhV%xTD zR&4$;E4J;5ZQH2Wwr$&XQZXhy-7|CgT=blaeX(!%^L^`C?^-W5ds5f@kj_jF5I?t? zE?DX{iGNjWCiC6Z4?Nytt`EbBKGO9^6nbaRX_Rme8atDPFqVm|*%Te}m8hMw@|g^F zs~LhkcVM&h7#LtfCe+Wvek>v; zEm1BoxWN>AE~^PxEzQ`5cAI4{Mn-HIs#t(^?Af8MJ2}lc`1jSYKlox)kgL#k4D}Mf zGli6EMhsf*gdvFT07ptreRV2)TRIhkid;W&(@%5XdQN)dJ^G!N$bHDOX5g#;P6fzkJ&DHQBIQPnyc~`hF-{CH$UDfZ;Qhr`Ju?|t~!r5GI8RY zpHkF-aNmetF(Fo981-)$5>+S3guhPQdUpm*sIZ2@=I)wwit4&B%q1sCnbIgR@>Q!o zi93rGk{ilZ%I=mLT$-kg7AXs`^1o*fcqx6Fl6>_83tZD9orsl(Dpbp;Yhp>-r^W0| z@o79G$8}T_4)kUH+f~P~yIJPvGP*Pzz7LyTuY~xbpa=m#fZ%6>U?!O?Du$q`7lg-) z>MhQnG1(h*Vi{KwC$7G`7QgK7U>`*!5rFfy<8Z8y#B$&;m5v^=;Kf&pG2@r|=?8Zq z{(W}9plZi``Hj1NVEungJijTJ|7FJYf8YI|k39G<;B{?fYjOvP2+1g+Kq!F{Lo~X|32l?9|l-b2#@Nb+SUhsppcPPwe1#GqmK=jv&PvI-nsP*!@+jR%x#r6m2 zMh*%)oFw%Nf`y>sCePb&;g0qy^3sNglfLo0AEc7TjBkpg@g5D5LRI$dE6pHrc?w-! z#?@04oym{x213a1WBoan;t1E6RR{FVMSILYVJ=kdHm4t4weChO~MO|xgCKhx| zlqhXcjlNtIBE(mF}I9tzfaai1=3h%D=`X1Q)jqkWM}L6annbqr3P5 zSOL4%JTl}cQ^kC8+~tgV=CY{3jC#g0cu`hnY&JV@^FnXo(0Cn~s2U^&j2aAC9kQL$ zNY=ACTru@(TieZCaWxBa`f7IM1)=hWQlis=e3C7L89^3HlG&pOX7%>BD4+W2=hAGx|W4-pJ6-ot#M3afqEmUG=U@gMG_8Qs9m~XwDz|}$VTZ!q# zv2eGgNH*j`fuO-fFD*-3O9Q9-U zXjPL=1iR^32B)YuoYWqBB@Z#o`ax2W1&CD5SLH$FICAFJ!8)-4Wwka&*dWdcYJudC zrTc78JG_a*t7n4+p0aH_o(KZv~uP!nO%WBMz+AGL3U6m+x(R3~;`FrKMP>qa8r13Q{u?djnK#p6g zakF3Wn}y>0!K0rS`GUN4%+740`Nb(ZGUk^K%%h>B5QvdE$=%~)KYxH4cQr+pHagFs zpg`Cxi0>`NJ=z&E7s?(u={6C~;lrIR2BRitOt8)$xT6X5!~4~LqA~d0Qb~9ZfYL2y z&?>NEhm}2Z`Q+{GKNsQBAMML<-Fwk3A*WO+*#oPVJ|~F;&!hvFg^D%Go!WufmOis> zDbI#(OKfN@aI?5Qt3ps#>@~Y-4VrjK4Msithi~uVp>+=vD8D0JLr1>k0_|o@pgU84 z1`5zTM}&7viTU=oQ-4N3DQicZE5HB1D0d?$0i_nO@?pT$UQ)5@Pf_tg(o?dhF$F=T z3ap{(tAd75Ei>zpQdRqN!s;Gk9u{71z~e&M_s1X!G*SXMK1cFYAUc(|?LF}NcP3jt43FxAjzm-0)rc66jZ6-CX|2psIzoe^=P0SR z98FKmIV_dIN~o_iHQXt-G0B}D7hQGmHy9|>T;IzwX&0J`POa782*W;iYD7vxpqMA8 z`V`B@t_?+%ozyM51Fu%Hi9j!3<{4QIyL`|=JZOiwtG)ky2 zy>PQ&`=hHWJj=l)X63$M#WsA@YOV}#I&p=& zoS@l9;3%Vtc_aXt@djeJo;ihJdS0!)T9O-tcFh!q~?KtfDC!LW}Jr4A8*VkA^bMXe%`yfK9Q;l1yme zUM3#oOLC-%VT%RW9za2m$&^&Ur`IJ&K-?yj0>jif8`p;D{aKgv-9fxNKiN=RpU`?T zXxN88xZyeC^zw``pw03Y<2$uChR@k&ga(BVnbP7_ehB(iq3F4N# z*5&U0)_6#J3_5?$jvHiiE&`8TBt`aMmK(n7K3KK~62cDI#qc<%zuFC^E(hO|2u(0k zM3+@?h&FxCVT-?Rg;9%7x}}`dj6E6OZhj_QOE|t-Y474QtUdF)yaA0jgd;iMkVqs& zi!Yol3z+L}eda1l$4D{7E#lTrbi#J7cU4eGdJe2_^`FG9PoZ`>w1@#4__x z2DmQ-%gXvNiPFZR$u~6Q&XVZl~Lq0n8db!swoR{sFhhV^MmQMD)6F-4F8J*j;H!Vsa zw(JTo_!N)G?cw!~wMz~79R`IWkq=WT(Ftt<{zq? zLG~pA+}$|i-#$;FVCeZ1B8kqsnP0KTeKwdPwDF-1FtsBhv}ZyezFI4-n=3*C24ST& zh!L^_d-SYd(+%o#QFtQCQUgjbisr=B?RJM>8hoB-_7%o{A?h)>dHSJde)3iWSj1z) zNW;jp(M1L**n>r8$apPcPJ5cQSTW(_H!UsN2N5)bX7))d#7%eC78zRFruX6J)_i+n z>z#W?%5T5c2c_zix=5$GEZBePzR=8i{FK2`<(bR4{SD5GZ&lx?372}C6S;^~crNhji-LZg+HAYu=>Y_W*2C)9Z7Ki;p^8(x~0}!M;CHm!|c}FV~>` zS9MM>`wMYkYptNBIfZr`I{df%?whv^{tY5T|L4F>$=Jl|pZoIvO?ne`b8^r(bozhH z<#Paz3hI~6-HMS0<>BfKgvvUy5Rm~IQKd5EjL;9|Y>*`vD2^J$I(yfEI8C(5YJ@4y zXua1#tP+BEO?`3&EWB=}eS)IwcBox6#J}TwPxe!-$M09ynVSNi?}r>ff?jm{ysyUE z19(_Su%Y@2eX$U(#w|C=n8AaL#Hivyd#RE3G7@fDVoF^8jxSh9Wkkc1? zcWyW$SvdP&X)!!B{Sk_jOBz6?=8k) z$@h6>`?^G=)q`!wsgPymK||bWv$LYhZ&9x$wSuu5odWi5Zj9HI=l<|P9%$Ttav_z!}G*qt`le48vc6Qb`5A*T}&P0a)p2?1av_8PCmC4{^@ zCoBz_sKs_uB7qG9mG0h6(roTNOr`X*eOWq;3sRf;Qgz76(hywmXnpp4oI{#G_WNwv1^Vb*wb-J z__F}9#3u`X>*JVw`TCo@Tzns}NwcJyLPB62LF8+u=V+Pe9W!*3U=WmKf7E2Oj+h32 z#x^pq++Sb_SY-(Dxin}IP?iux1v|pLN;h$g-oOmh&zL!ksOH7~DRz>5W&ZNFY5wCa z#Jjcrl3r7Y?U{%BZahAxz26{GDYlS$YY{e%Yl zVP8H>_iMKz1^!GjWqJ3m48N~N7fHPsNeo_Z$i-&wJKSi{1<}LVCKAU z3&l2?^rN>A{BP$>ePh2SVOl#*(=*wlfD&mRMZxe#2tTvcU;Nej`{wRq~}LKxBf z+TVG8s>>40wKyw4Z)xPBkTaACpt`{*bY_KV@hW{PtZ@%Y0OZ!8We)OK~PJ``t>d7opy?UJ{6CLJ+M@k*7NO$ioYwaz?a$eP__qPsN%hIu2kDHQi)eM(;JTbB;Jk-|=PT9*Q zkdM-W?n)0>B@0)oU41E6SleG9n+vQZj8T|Z`f;DRs!Rd4J-2vAH+<+fKQ2E*$#B{* z1!rZvznuN2M3<=7X5@BU5<(C!B}v;)(KL66HrY1_@v4Cs5FY1oR}7Z?GEi;7x{4^P zXU7+JnYd>~6|eb&X!+5(JZO(}n|HH1TR#M16`8N84JsxsXjG(f@5=#+wRI^hqo8WgG-@_fxDJkrI@Km%~ zeoiYlM`QP@nCPiUG5J%{BXvrL<-j&yGQNI-|9eTMSYr4{|DZO5mv@?k!Ok%;!;t=cCBWdb5>sF|E~o8=1!0V7B5Kbi zFk^os({8sAViD7L1VG<$(yPq7-)D|cd>fcy7wkD!QNQuN5tPDvvy1V5$IMY}cQ0)- zW$%~`)j766Z|680q<1?aYT_EFXm-Gcp_`)6(opF=dKRscp{3f~-0WgaJe%5zevhktEn=^8^ zX!T9BMPK^0e`i6M)eA7EhE_)o3;E%}{Ozq0;pG|w=IXN|&s%ZAA0$vQk)ULHBI=!Q zqQS(D3<>K9Jo*CLo(6XFK+$RrHlXSE46Olp#}QWB=7~m0l*)2nz=ORC)fQGa*4kxm ztx9&88R5=dkjmgJry$35bg2k!a*Dw2{6%3=@eTd#-?YWc3i1!v`CryeW{Ijxo33+ni5=BOFmRV9pu?^F@`N1n4H zrWqm0cri^E(ILqL2Ec0;hv+mtV_8OnslF9UzVn?>T4h_BrRF#*9D-V8eod6Nhf;tD z*!2M?w&Iesv}#SoHXhv|gM?GwErpb;fpqWvz)G~w{Hh084!#6}e%+@sFzSWnvc&b# zQDuw$Ka2I$m#(#L^l)%PLcKqE7sO}NK=Udj|BNE|SfedBrw(cuFjrOlRB3xw63*6V zp6^&%kR6#5K#%^z`AsT!TqW&{X|Ft&m7UyF#SD;302CcoLq}!)Vns#}-LrNj1Nq^! z#uf#T1)TM9ule+Tt~!lSiC>X+hX7FbcV5KhVjDO{LDszpN4p9?KQUW9wnb4*2IiGU}PvE#i#J zWbX`4whTtFJGIuRe`E-T$6Q&94FM`pOL zIt5{5)C7gcuDbVie`IIyvu~b=LORvSPN`?Dp7616%c*R&MLGb<*PcVlV;(@&Hc-X` z>*@QeNn~M-LH%I?FzJW7fUoy=c8XahL`~(Yt=i#1w8msWJpa|Td30n|bHChv+Ed&R z!eU24#WUL1mOe#J-tg1uTo>+bnN5mI&uSEbKIY!#pjB22hsO&qByDN2pyXlZP)P|7 zQGJZfD3dUjE9V}rbtYt5uyvsyKt4HOxOdRhfs6XK`ZHuvQ1B>aQT^bteaAfKoJ4n6FW4a|Q`zih)h#LYtyJx0dnX zb!i41Z#ifZrIiW_g)rpFrBFXeX(iFi*^=8XjXf#j9F{j%YY$%k0d zNjnaU7M=zxjI$P)i^Ip@(bL2tW+UlC%2;x&I*n3cjI)^_Y}TjL4!G4sSa@Q#jEou$ z7z1`b_u};uQkJLE=!*k;^WZ#?7PbLpc`a6XnT6uH(Q_=pPX|3ius;R%m>jrhClkS1 z=>gj2ReK#`Sthyl+J7``p!t96rl&z;E&yS`2+<-Mb}tGAc8JCAG{`%ym4xL<7|xyo zMATP|gbE_eHst)(^$|tlq5*}wcJgTX8B1|cMbN~7l}D|V$S+p76c|o_B&J1~YAF>R zi2(FcqR8u^A_9lRyf*ajCm0U1!8M|alqli;P6)jhjkIB>5WOyw_T8$elmv%-a3rZB zP`mj*UrHqmP-~(d26g)&mB%6~HYRmKrF+!|1!hne=GRz#)j|!D0M(2g( z+U6g{N%uePQZHkEG^j&RQG^6$I?4a?4Mb!^@UFvrb=(h>YaWespk_&!hYXT47U5>H zIWci)8yAvO$6}L_P(+%~%}j z^#vZ{G}*KK$B}<6aPz3F0!5k16sBw=ws?#W zOGU#tU#b<;rWLf+;ZN=u9E#E*A9`5@Mja^!(u9m)l1>}-ye+@y_u-#X3h=leMXmzA z^D-KRiKSpbwIQSqUYtChH|L0*HtMnFjTS?CV(-%tYx%UdUpx;%yXrjUAV5=VeP*4T zEKvx&@)Oq$0deoNyFZ;{Hub*0MI?nF+VZ+$!7xam9Pkkg)j_0r>xxY3+$yXa7cPwD zgkmCsw2zcK%9#E@=g3JjxOk%#F>|?hC%m65Sv@!+5s+ieCKTkQ%B-WF60zmCey$jt zdQEMqKM_ep(7dX6@aWca?1;?n7?M)SBJ=P@hkpqrLXq1n2UH)(MfuNu1-MDvf8kH= zBTTypduNUPZEQ-I6UgA-4L{wl%ny5uHt?+72f}S4Ig<~m{*uH?Y1Ds1;_GsE()`IU z_;y7a_JuljfT2j1)BBy+g?*4RL)sn5bw`s*k<(B7!mD`zqfT8;vB$jTJ%93c;)u#& zo8sc7TfTbfmg=EhkFk$rYz-YcjZtb^AitIN@G+X>9bx9Y&?+_+v&VF)7a;p^fP3&d z)$0?vZTNy zP@7%X_v%Jo;fuH=0CoPOuT4&!fOr@jrh-AyN2Q{qvgXLRr_Q+7X1uuKkYrpHwz~3n zjTCK7SB17O<~fb3dd^6oimW;S@?5OXg0OauRL{#^`)W7w+f0G}7zmItV8t_}}e;#&6@bZ#xuxi5JuYUprWR zHN&d+ER)=@^r{DPc5&vs=0gOk2e7@yL%L%>(e!VvTdx?rpUZ(XZxbip8ws}KK5Y-e z)kM#_|L!&d(GPBqPPlqMzX8!FbY?w6?B2xGy?Jgmcffy8TzpBU`zF6!zuhqKzn2Sr zBtI`reO_(;@NVbvbVaZVb9KE`C_V3@vbW5q%NmJn_=|S`XJRA?TBX*iSV6`pe3@*{ zFu5;3t>8ABZc5O!ieaghhJOabw_HfLqQ1Gg{678pr>&Q(ukG~Di?u0TFf>O%6*X8r zMOR6CIYrg6F@3H=77k4$JbAFqRU@(_O?6EnsS@>iljRgN*gc#vi|DzXVqS5Bc}1#J z^QFW=3wrLr%N{yS7I)!JGqYqyMGdrYSmvVXrVwF>Qrh#b_7*j&(yEN!8N5G0XCt9G zcz#KNN&3-xbM;+fU4h*^ihKy#y0yVMHOs{4dT+LAEA0od3U^X%TYLx_Y#wR{4j@h0 zKA~@`CSY*LE_&s@@vD4-RZm=%Ns7{ga5%eGI6&3M)qv4DOtfA&?7=zAOKRw`P!U%a z4V8N;M)qnoO8C)iRMN1KEph9v67uF2Ze zh*=2a00M#rSFLPs2*C{H?zy3kPMu&;i@BMdm3ptUcjRzgKk249jc`9g$=s>B3vEA6 zWZ&c;-1eKMBWqr=uR39qOT4JQW)?s(LAe%AX1qd$)VO_RpEkl}eYmnxfHTd0SV;Ws zU6hH%BX|DYAxd+S&0m;yYkVAh`iQJLog%cWN(l<+LB22{84!nV zA;8vH5sL6qwz7Q#tb)=o@8B9Df6kEGZw6rDsC#c=L6Lw(xGzpq%0Q?qA5yN(arybOkv4lVD?5iY}{ zRhb#wuJBs}&XQRTx*f2RY}TptIX4HXMU;9Ue_^Pq`|OdfcBcFrRZ^38+suILS*IP@ zV&sCIWR3*6i`gH{*em;+EjW!ShLshEcJHy zbF3U;4UX(!uXTnmM3$CP4u@wP5thGP*>aHoA4u1$~PlsxJut#69*2;^ts$4xI zye|Zj32lb8%kYMV$an!gWpMgGO=$Bo=#MymneUmpZ4UTC{dL?p?Dx%hCU~z#=w@V+ zjiNTDPI1VK|6Ha4KHW|lbw_@LzUUDq&A<8Ng()9U^zgC0EgJMYm1 zs8G)+bnKoTnb^JQO&5lj*tBDIZRrfTbTk9nVV> z8aqi;?b`qFP219V=jrp7SB&hNnBzwS29wAB*!HEXL!I_i0_3#4-8jp;3M{MFcjjdgz1hM{9*XLp;c==$$k1@(!gk5m>SavNEacAg6R}O z9S?-?hPB3r{^IHZ*sBJWv?J(EJEHb4jrVP~dRS%KtqX)ri#TRwTaOsD60l6!l* zRO7dkCXFAXTpNX(dj2lB?*GB?hC?z-RT^puQYCQ?x)B%41WbZ_C)0yso)ySpRKsP4 zoB5kz?hf@Gr8G2C@YgmfHN`Kn9O1=)(rA$!(M8a*Va4&mGH*pgXf|AdyqE2srmT0t z1AOgCgbDfuMB~_zWF$bM#Foq{hvFS)(UxGCtKt}r9f|KwM>6UU&QbvdTM>|e0iwi{ zfg-Bea4kSShAD`tq#XdnMT2mjH8bZris`OKoE#!PkWcb6q%(gs5&1Kp)FX9m3K z{H_&urff$2jr7{POMK3!8(DW-TiYubR`ktDsfnAud3}G)n7+C(i?UMq>iA)|?CpUU z?;R=jlmQY?N^HZ5A?q@#e^pdb(W0?5#SEpg5kbjgguYIK*+$ESW3+;FW7m9xeDIbB zjJ0x42BTOve?^cLEmLEVb}%IH1E5AR8q`|~#yx@VAO&)C*e9TUQ+?|S$|IQrkJk?^ zPLkH<3B0pPK93*!0km`YH3su6R6I()8=Dp1e|gacG)g0ncmeGh#C{(Sw$3#V*cC8C z0^9Lq$aYNJf?(Z3aDGcfchG3G)^meA+wopGG+8*1iGzD-LpUO=*^UF*sMo*to0f{h z_dJfoc*4&a=8nArg7esPTf4S(k6FIJbTEXV7YsX*;l%TM3fnjK)4;KSBDQ6Mh5uu1 zECD`I<#lJ6(<3z4HxTKK5`CX@*9#fL&IXSE(oGM~6%v%-R3%Vh1~DBEa+1;^dKxzy zo8*ulWtr@nLu=!>g_y$dA)IV;wqBjVk6;bSJgsjoTcW`kdYn5l)*d~Idyl|aL7Lhu zwB?j=|3Q!J$0$nuR(p0IaL(Z%g`(du)`I+udDm}pnHhY5Q+i41bcsDzS7`YSEXqMW zd=0j?kZW5O2iWOf*O}%`-eyqS`T!0S;RnX|?J5)#F2?WmM2~V0crt&$;hRN2!0gOL z=Wt5|p*nj2?5!%_cQAzjMX#)qI~v;%z$)QI^B5T*V!gvzmKj!D453H@VZ7IOyP9-L zQIMc+p7~omi@5PDvA|FF74wGI`+j_35awY50}GKsAFNBrOHUM2uRyI!M%EioZ3joj zXPdOnmII7{a&|bhtS7IO6XI`O-XqYoJ7=HaC9n>Z=%W28YOEhgB7-VyG z1C6K1YS7S+VGidm+(p&!5Gmii;&Fy+`Uxy9U{v?aL_Z{7120h2=_{64U7!1*O>%bF z718?EY==-=X^8AjQ2BiaB5{Mk>j-wcHkL!_*o+QvU0=dDgU!n{lwM9f|xytaCQShiXPdlA{rbo(INCjZ4Cy~8=>!9&Xnm$bqZA4C#x zTpOn&B01oRa^X0U57CrUykLcMPb{W)Ei!*j>O(#(&O3P>i?LJ&b19X=RiFhg12V>?Q7vQ z${YfvuK9YGeYt0jTbRshOR!W|2u00Ui4EAv5!CuT#|8v!c{a3D` zw0*XCE1-Nq(Ms)lQ1CDR!Qz{Jdt1uxGjN9%UVrDAAT9u5U;nRtWcj|_*7{UTz_;SD zE54V*ru?n2;3^@yO@7bS+Bs+7`V?1fIyXMjmeG*^_w>ryXGQXpqg!>22AeoMe9iNCQM93gBM`3P;l70gTen(vdSJ)t#!0-Dy zUsX}H7~|7q`M2bfUrlYU(dzjmWGaoz(Ih90i^Z|Z=JR+H0a$rgUbkXsU$^30JGgQ! z3Xi{RmkYGrgMtlj;il9Nz|LN}k%bFky2==Q|vDdmd2*1iK2nt(Lva{-|_Zq zu5D`kV>}-H`cq-Ya@F{PsjN?|u$nqGG>F){95mr9KhCW$l$1N_CN^!>tg;dXbxlS~ zSX|B8Q&(%ez3x%^Kh|IFb2--*7lNvzUJ;1F6w?KU@i zF^-zryvq8dJ4w$-yV8e4Z2Pyr@xjy`j!ej{Ro}q>1Vz zBWc~a3FXeS_y8=#@KkHzA3T%lA+;=4WhY|oQFbLrFjQN*P86@gtgfoktV?Q(vXefB zl)7w~>>*qlOAvdkT}GeJ<%%I_!?Ml{a?=#kdW=&~+BDn`5$ibCu7xRGv9{74qGd}C z!{vnY^yv!?yz5eu{dUb26 z+u__w&+`T*)H*P)6C#Ax#|z4KLq~4#*QuJFr-W_7P%J~2(Gu+TgAyW!Wuzy<+$SQF z@(&qQZ7sGNQD)`s{Vw5d0ke7P&8wJ7uGdfl7*t+(88d(O%U6ch$8lSFL!a(n&2;1w zfxi@nHX)(wii%B zBg+{6P=#~P4=^#B2Fmj--pBT-+Q)d782+JNP@n^cX8~D8K47#p()kW|-twogDrtP7#y?;TQmr|S)ns&R@a&`| znjH*Zq5s2d>6Yf<%nfqg`5imQ?dDJPc4^Y|4Of4rcLcXj`Nc}$_H48u$!s^J4LtTz zl>3b*o^KC9()g{Y3tECya&=0g&K$SFSY*^#JytW-2-7fx%N29GyEK4V`jlJ0ERsre zD|>c6L4{rth{iR7rM=Q5udjh>J{1qdL|>424SCaY=q!@+DQTLZ+q6%cft>)Kx$m~P zOM=ye+?h`X&5?7)GlJV@kB=-Vb=;(oVhc^`fu_=}zvq`hjs>WTHKf$A6M^{T^H4Q% z{&r|{T0hjHcBQ$M_gdU8@aC*UAEc;Rk5fsG^Q>Je59X;6htozQn0l)`~c07i-tPp=mnaw*=CDCM0S;+jbBe24As{9DxY@_i%IyWW8r;ox-3 z@+t_(5&7hY(39{92w))IKG=y+ES3s!N-L9}npYXrbj;v`xNt9EYgg{na%|^=xNPlD zr$EWr3^T-NCCdzQtolMe$ZWJ`5oa*nQEa(ovmz>@;LxYRKd1m|S_O*Q`19z2_Pg5v zwF*{>NI>IvfQWm%pXZnmwd_?>9O~cShgE8S!Eo-upGxn+w}hvXrR_N0yj#^`kA+gU zk0p^b!$;(iwonygi62mzs6E(}^thB|_bODKe}>tqC7Y1=hz(5J z`e8O8$v!9*BQ7&$DLcsg?GB)N|I-@SJvZL6FN4iBy>@RZeka$c`1TBd{E(6CvTw>- zWG_3yh=Yp#y!ttJ0X=?P88eUZ75MsvU9fF)9zrog(c|VlidC?!e~uti$nXjE5HWlL zVeRb$M*7!rPt|tcFdMM{xcyUc5Dry&>$mByvs!CA`La&Jan)^$CF_@S>rfl^U;~nj zK+I`4tz##6%p2fnS3ui2A!WT3<@*1mJd`M{xCN-{G_|x+to_dyelWGBy|NX zB6BB6)!xJM)6Fk3+^4rUMZV(x+7vn>5+7p{MbA}!Po+morAkVri(phkFHkD0RZafY zNh?~v@T;9Rgox%@(VYQ5L1l%Z++Jd7C$VDiybj)W+(SEo+l%z?voiKAMk|8e2>843 zRSL6toW>mWAu^)yT9LRvGhxO-jnkOoX*^1u=+=R6X!C(!D=EUL>?(bZ-LYQlz3uz- zgZycV?>K!5xqb>g(lRWT)1t%#b*eROxY9B%d${1=KRfAz@dQSalTJysZV)f6jO)%2 z<94y4gL}0&0r~NhDvD+5I_O1X^blNC*t{}u9P0$#a+e@J0rehq%aZr*%G&yY&-reW z>^a~72mSglXmlt|$};4eA<3JBFX}7v$_59f=DUm2FCU^b(~9&%_*H}y+#XVQkc30R z;<5Qu@(?$K>0e#AVvV@HQe5FG4v{(EBF>!SnP`jGteOj#@BJoz{px$@T0mz53qk+s zQ2l~WdD0)&+O?pICC8yzkB$}7=4|n~>JRO4+uWa>k0PysWTutPEI;hycD-3YChOKc z$bL7%j)N&bC+iN?!BiYzPmM-)_E@N2?Vvxaa&kTnCt=uKw>}UV^MZT*x_`DqyUR-( z9qyG!P`fb+()&4Ia%axo6lZ2GG7`NxVozD7 zCQ4%%-6vboTeKAJTEnFrUf`{E;0$@{cQ7dM7#&+**Zd@Ga#SMZ)E-d>IgfYQ!e*E% zq&?0|8=FOzMV~XVnRBw@dWsTcuxtm>N&qwEjysyF&~QSj=Q;;(&o@0rHkD!UtWp@k zJ4l;Pc3m1v%jPqctnc|$zYFIwC3i6K;bz+9a`AcHsZY+DP6zFynr~!oA_-H`SSr5A zOyV#dshw&xksW@3ez11%dPkud?^NMb7PTV#Kw7Vz<2^mH(>G~~ZN9^wo~Fe)O{nD^ zPs?+${DH>)B?d-pGv!p@AC$kLzF!QwmgC2*nwegQ3nHclpP?T0Gl!aUS(aiyXEv63 zUXA7`YH(F!ToRCh6mrs$ry-i_=bAzvA3qq;Ddi~V+*TiKVwA7oG$(~?qtVp{JgP8E zZnb0&^h4h+UPx0M+$kX1dyccn5Ss~4V})B+P$sw1!-%_Trz{%R#OdHL8pPz!)bD7^ zU%&nQ`~u-Iel(ChyK01l5v&e;FpaP}h9u>RZ* zG-9r}64qtP~`29RT;7;A?2zbbH?q(vX=))f6|)V$J0UU}4hsGE0(*I;)(rJbiV zZ)1+wFc|wwq-9v3!cwzzaCpQ5;?0m)PZL(?9&~7?X`mtxPem?LQ-vlgX)SAH?5u3$ zp?S1QH7{*S*LLYv3sP(&NG$Q&X~`*?d5h2x*CcvCtbADW8f|J^8Q+Aue(ln0sLkHv zj4S@$E2^(ltJkC}l`mERJ8(j?NoyftoK&BH8DEHZCl_36b&1*#qe-y1&Y{QUq3*f| ze&BslZ=PqwXTmKoy_Pehur@GC49d^FVK4z@K}d8^FxkV@s!`bQy(T!pIk;ork5SQYXdHcQ-v*-{udcPvyEYbWIg}6cir?`Jt z*2#WpaCYO#F=Z|Y=FN}iKpM7-m{On-KH|~DusP)n*1h;rB(;b2Y(j@yq5>+xk{n&3 z{#2(@!p@*Oe-$hPE{@vt45knlbTf|fniNsa&=|DcCgzHKD31#TR zTpid{hEV56=GK}QT8A@HHPDs#Ir&IAas9`8Mr# zUR7S?+jjU$%$0S7et&x>@~YaQx718{YdBW0FJ7T#KV~V>+U#g3uLM5IbENo$?x{rs zIG|}`Pkuz>lY~zoy*1SJ$O-%{GTa;RA< z7hmfKgJSk|p)twoO~{d~2^|TGH6(53O;vf$=d zNS?PylF5kwbj5#$aD0~Ud!KCi{6je@h^t)4t(-&&lAqvY98QNh3r~K{dj^|bNrycP zXMxR>PJHNY3Z)m(jW&0NmdlJVnmxkN;NNgY@#y{$UfA`CZ>>|6^_crzg4lKPZR)Lflcx z>)&Y|s5&LhRF^XjG#HBXy18@>hN7ZcBFG?tMunh(pxeRBeX)7-4S)c>0h+GRIFW6y zZ+9@u;vZSq=_}->IrURpme-wAHojjkpFe*47h!rZq4d+vF^!B!j7X(M5JkE}wPKPU zD+%$7ZI>WJBWFvhBZksqsr2ijLl(2Vf#j*2OJGQpiK%Q`WaFLveOk+tH2T>{o!(l# z2zPwpNAxye23e?5?o*+R>7LJqBQ?1&ZJyqwPrdG3Uc7uc?a9k31p+lc7tK2}gT<4e zD&HuduC!=vY%5M@tSRox_<>24%COkR+IUu5=b}4n*`%-Hj$ySV>)^`V*a|1D!6DPh z<9brC+mLYLgfY?x#a`Z6+-bS&d|AOGUv{bcxQtQ$!i|50j%U{(vzZo$+OAr!JG;Co z1i@`I$%Djju6NRP0^$HJ%eT0z}wVg<>B~SDJE+lE__nW0m~y zvzrR>#By1MpLda_>Gy>%w~O?bML8{c=9Cjs(bqPF3;B0~wcjkgeDig6mp2h&RjR7+ zFsm#kzzlu#J9pOuXo?qjjXvta5jpR1kk$aS`G~r+6@05@nNRlVnrq_F%uT*GP1Tc%?l< z->O`+#M9QVN~*<6LZcV$0S=H4EcE?pIoi=|F zWjf7wGu_Sb2_7pZJp|%_d^HA1#1QO{c_sNQA_nRXC5ok(_l}waB`eu?%#4bfPdQ%t zizAq`E4GFrZ;TM5JjsLI)3YF3U!9Uq)mLG@&7xsWWqmGkiM-!yinXoDVg;gXYhUq# zMZ|LPRgO)KR!q?_bm0-^?}P^`gu!6i_Ne&n;ZN!~ryPA%iB(E`#CiqV!}Ax1Du-tE zF7Z&h$(al5;Isi~#Xhe3QLL$C)_@exOJSSK@(^we_;ffG0R=kQk!)rwfw?x=uz2&v zIk>eKiA(2syexwG0#i#5kC<{<8?=RBYfX7d(!m{pE!*>|bfO%){iO+~*^>t==&bU~ z$)wYs{iba4-f;D<5w7GM-8J%q~Ot{6Xq1F^5? zZwr+ewOdfRM4Utv&BPnHe$Adv6rv@Nt?Y}9%HS)sc5OCK)c}mlrxr$~LaJK%UM;tb z-6Qj@oR#}ZO#JY?sTx)y;g5H^XG51H%l7 z4D2{XdpPWIFjYA&{}J5!rG(^cTs&6EJZYBPep8x}$>t@sZrRw9MJdg(Q#C927XzHd!`u(*+727!gaC zw)xpJ0|R4;7d0OHV!SBg=Jz5?N5a|WwrF;Sg5>f zQ3Y@`ah=EUR56|V@!EvP3|XJ-!%5yZn1r3jaaFOBj{G<5v$9k3uH(-QhIfF*%Gthe zC#ju$hJA8HwGw%I7&{yYkCD0nmP4h=WPpII^~f%GeUAu**MI9!=H@!KV~lO<1$^XhvVhb+jESI%Wnf zM@q`M@A*Rip3B@Rk@WG8u#A28fzco^J8nUvXy7-h3cQ^K;+l z9&})btd?$&zx+Sk?4W8mxz1pyv)p4EW$k6QfR6)ti|j`^PG@}o>%MWDz;WM*007|l zE8S=MpAJ-q|JOoA_kX*o{vZ2PwK`0i;&Qsr?DUTG@eG_lz#bbVy)Q(e*k6e6J$7*L zKLY>(E%1!4CO`xjiO^veDw_?<&6fW=OxHPg6{QDPZ)ix_OYn(f^n`<;G zomW?sE48gZavW`G)6;KXxIbQ{emzw_CtN38J0IOU?XOe0IoQB+#0G$Fb0>pDfM%x; zh9JK@05{bDJ`MKk{zKOAP zVy%3ucLg!Nt9OwA-+y|m`WQLR_=-bQ4-M!hx2YUnRXKH%S${};pD)~`M=u&aL;-q7 zG8 zW|OM61j#lUabvEINi$t1MU3SG?m#si@5(^eDOO!V$hu?H^6)d-|-8E-o1yf{Z||P|H{| zb|j5WSsDgbO-pm z)S^&4I~s9-kS4OM!ac}%#P+EhTlb{z`ZCccCC^2#O^L&0nY*?F z1Z~X-u{nyHXIq9$XthXYm}{3}iW8(6Lf6)wBub4In=$bt-5LpU9(!_~0!kmrW>9F6&gchZDVFDeHLS_TQkT~lZlum!| zc}y5Z?oPwzq*k`OvZ_ywQKdXf%x9f{H_xt+TL|sEw<5|eBJGe{C^P~Dz&{Z3{nQ*f zJjo+k-FL(i=W?~iP?YJj7{geh{y1%`eXR20q8!e2Bi!ew()SDo_4I@on+WA7Y3iCl zcl5-Q`Jq_C$+AjVZrV$6_oHQqK#DQiL~Vlys^GL?STGC{z%UFNQ4DoZaANov?DC_% z$e!%Y_RG)kTcQ zdB?NM9pc|pghc~PX6cDEi%!V{D8(a?jV(!)WBVC|g|qgNN-_7D8K&VEhoS$x?CF#! zWQq@k*PEV*H+~dBvtQ6;^8p~ zImfBydX_d=BiZ~rnxYa@j%6+y8176nns#j*ensh28H=cM{pH?Rw}xxKN|Urh;Xz|!WM2Mu(BK> z=t9DgYbkz+qC~T>lza0p&h@mVj=HdLG<=>uf-Q+)R9+q3&W0J-$>B|m-Icu7-Po2e z8!rWY7^iv|Lk$oP0F5*chl-#sLKbu5wX5UM9q7l+Sid*Iuxt7D1(H{LEIq(ldJsT( zP{+&?bk_s>`tMTJETt!!FV>zYO$Ea6$*Yl?<1blo9g?`tf8~)(rzkttFtji#p zk(jd$Z<|%Mk&AQf5~5uw2L~Mqs=bilrOM}3#mY4@+xOdA$gm2}V++RxPjpo0wLOx5 z3+Wk{>RrDI))VtX-u&tJZsg43DYU(|`#b3NG$6R4K5>?A!dtFv^*noArpI|K9QijN zEANS*MU*QFr#Izam#LE9)212S0Y-n_H~-H4DdpbZr?%_^cA(serjL~)^X%v7e)+IR zmbKglp2&dbY-PHS$ZQC4Y(SAqJ8VF0%B})GkbG+5=7EvWYw{xrJv#mPEIr^(m;Z^% z*``2-o4>4MHRMx-a;b{+icd-~{$g`>C9rUBba(qOYYOjMfno*zLsMz#@3iMbX z-u?I2gSzdryg7v{Wc*91XB?}T!xe?AIfSUZ19lig3I_W7&kOBP*Op=HHOWw?MN*c2 zq8}paK^VidA6|;n0{qm6Gu93@mV6Tx>>AVtyDcTs2hb3FOQ~hiUEg9Ly6Ky1s$bRo z>&0xC2C{()9l7_9dhs81BqytWm6&OJesdZ?*ltmV zoI971>l|~aiKj#VYD{FU;-;R0y13vWk&4yE4EGKQcx~C@j(g13Xb1>h;SL&ym2N}2 z`^Syg1(*U9tDtX#z4X}>^(@vTRe8z4x?EsiPw!EB9$?1-Z5hD08IRBbW0Nr{fk?b_ zj+_$icnL{2dC7n(;rDO8xDRLvKk$|H*h=DRV60?E4W)v8O8SwCz7vHF@y6N32C(tx zUl?@2#2@kEPD9V$LLcvmJiZ}thaF-2|1xLS3m6V%x!!9nR#p=*01HU+A)1nB# zb*mvf&c&h#l!tv}fnN{m?qQZA6S>`)6TR1WAri>m zKt=irdu$d@Ge9ghd|8@;%sE3|jxo-dU=3JQ+N6(Krn^__&3mF7UraUof<$mjUa7VJ z#%gj;r2I@7Fz0wXI`UnO|Dx6SxDzqBDCoYlHoZY!{=j<1RJLtYxLb!MZM-wiTyC`Q z9w>VJWZSj9dYC;)%PMDM7S;YrTRB+*sm=JR*^nJ-ueGmpg4U?coTsA{1 ztdodR5qqSs(VUZ7P!FS zUgdJDX}wG8u3gxXgXu`0FeTtJvz*IMT+LGe+)yLrcX2I)m6!hZT@u6AjdnTEFBa`A zrxscgoAT3K>Zik$Co)JQ%$VzYc4EM?pO1PNUXN17&feG3qL>+N-Urf}{gy5OaSc=1 zqC?%)uLt)wV8}tXUL#AvQH)lI!KBH{E*7;P=~pP^{Tuz9TsBWYmJ*sZ#dY|*`WyW| zSvJ3_HmRi4%z|Bc>|V;s44c;?Eoy|EgUg>im95u}0wKE;euHe16j6f$@gUL!FTM(mx{E43A5pRu2ZGd!7<(bkRj<(O5SP10k9+G8n7Ff611epBK z#jW#ap_Btdvl#8Ol|%jNV0%|p7`;u~DlgXAp%ioM^? z?~ew}=;z}KB2N${>HVdT*GTuDWJc(IlW-RXbW?HVJi^>B;A8qdjL4RPFYh!f&EX=1 zb`(`xqrMI5BUf?jd*+~j4CyzHBu}t~5wr3i>Mk7i8e3#LTFB2hBX7l8?4{%qC-;A8 zk+@|S0u*Q9bmY9)YJ-Tkg~o!qqZKeIxb1gjsv<9nap|aMEbOthji%u){+RLDIjmGE z20enTJgk-zS&77Hs8r~`6lz=ws&R*{?-N+845|^~5&+@_k7F6b(cyOQLuipb?~B&s zwMP7L)4?WQhn-(_bkqK&Q}7T4?2j5mxv6O3`&59hLcI0%6jqd+8bqBJqnK-8FEk-n zLV3DUh-6GxxUhNBZgknKG9u9>Cb%b*fbl76oRBcQ?B*)dP!-31YBkuvwK_^w=w>OC zkRFur-WC-1P16Cn)+bNH+N^|b#D9p&tq9*?Du2T$g|peGxM^nFwKNA5*4qEoJ&5TU zQD$rtJ7T)j{E7dvxW^;4?w~7}CVvx{{DRfgq; zQb$&D&c=|weox9f2P^O7)s#omFzQVyiQM;5b;Q5Kv#J3H5k%ptW02A>evsT3WtNgd z-Ju|9p2pQitc`*Rp`yvoKCr0SZ>bPc&bKIUOwO-RXZT*{)GT&VnK^LK(t_+j+yKzs zLS0FoTd9LtrDr2nT|MCO;!on;l|KDL2B}G|3*SqWx;=<~$4eRxr*6q-z|2c($|qd; z3M@I4TNhPVyK*YxNL1(^zv^VQ2-GIPWEZItY-`5SCW#fTtpV=6!S1D+>33tEc+0(+ zYgxKSVvV_7@YR`=C)@0Sau$l7S>EF2;m*`Jv^bh!9&U6EoJEl-STwvxDBTwyaSpS6A1ob0&xC!CAo z#e~0s2{%aeZX_R7IU&>F4$FEQsKiU{4LM2OFnsBI8t!=|qq&9^tsYfZWh~I`^dwW& z@Srrq7BG2bgd=KVyL5ctz^cP0MC85kc`xbnrk=N~=x5DthrcpPWKCk``T*|Agkj7T zGrBqL!gjG|14c-av@tx_6ntxu%D=iHS4=a=Zp~3*d1W@IvL|KDa%_>BudEp<**rO4 z;~fL66Lq^B_oP8)v(jM~nld0`jfA_(N;QT?Z-gsT4b85P zZud>0*H;o8GKzwsMZEK8>uf?_wKa5kyZ7P0r6B}^ccZ!el2BoO`^Vh>e|tdx4S<>* zKPfRN2OsjYI3jxRrE-&3!(44bP$p+jL<2q?Eb(FRGQ8 z@3<+OT+`#>6Do<~za03U_;JaZj|DQLU1f}{c!yWNcP! z5D;SpU-uUpYqH^5seq@K^i5R(Jm%L9Z6}_+rCBG*a|jAye2-lm zWY9}RWXBpC?8M%EPp;w<=PX+Fz)(d(ZCaHaD9`_UC_Na!lFW2J`-^QU4$V0MPzVfAs$YBmJjAS+**KC(;I#hFr$=WEWNG&+{Y)4Q9zv#Ugg4%@T?_Kb&_yf+N~z@Cor2du zB&h#BGA~7**F@xBd!0{iQXkyaTXVV$kO5~mK{4+VXtY~(0uNDcpP9(n11KHta5~7h z#iLim9xc(m$YM7MtB#^QbC_B3vgna$r;fWa`zf<1tnlxV&KPW#!jyn@{rVN!l?_+$ zbZN+mj##oPz{Lm=6gQh#5`z^~kQ)96K#=noquTO3Mr_G6?eu;k6N_GZ;u#cOb_|w% zuqY)dZm!4*7I;Z2GYB%puPga$Y4Z47Cr%oO7i&np zjBtA+;djr37{r~W7w8X$Q9`D@G#sDSC>ZalBYBNMRb=KzE(}KL!_`^rUs2YuT+^d$ zTh4aMX|jn8#UQC=vN&Z+}Zdhp}Ds zq9|pkG;py4@~pZYK(*8RdX|y%r^gPPv}=USv&CGgrE}lm$G=AQk%gwGk-_ zi|eQ`t`Zt^8*9FZkjg0dY5tFi#5(c)W&-kt`SZG9xe{ZsA#$qoR*dQJtO<_l?Q(#$ zqGx(ct-jPK?4^+s+1O@^1jeYy!JIvc?&>WJ&dyM4(C_dlEKhRK)k$m6k+UcA=1z*j z$kwx@R`$?8a=7%s-Ai{6&gm1LZ{f~RYvmRRhY#go*69x@8TW2 z&cYpIjiQgl^SKy)`N50ecSsDMUSW*t?Ozz*g*($vkwM+ygkJO4&KTd_TuxR!qRy(h zMbf&Kb&hf(5(A93WuY1Q_}rC5#(XARwvXu77PBR((g(LPYB5xowH~7h-WXxHXt}LZ zG;uUDS{Ke`zN+-*nV^dfM`h^ItU9u8);WgsJ)yG0{1vKx769$xI?A1R8<8ZEDx zF$SfK=<2A*OmqeQgbHV+&U&4m;M~z_Q0Uo~EUFlN^Da&lAwG)~8weirGm7$`f9G^} zBA*f(Cv-DxgAK8Sww}$1ThooU5*gxEr4Z2VS>!3!wHZ~s22~zJ7jei@V?iCUimRAN zbFzn9kQ<_G@sylcoFl5-CmQnbwSwzBO2lO1e>=^%vER8yexe)xIXSh#@IRrDk+1{v z<#DiwZQ;Zs_p@G`sh7%9nmJ}la&dg5ir14w)i?yQ=nPO#vR1lSvb=3sDlfbh6-1-Z z6+}P!Y<;5JgHD?*70F_Gm^Ro@pNMTCof>wa7M9!45&GioSr-9Qis8K+seG*$%RJ>T zbsCH1D)uDVY6jDfG2ZucqA#JKIn1od>k7qxlApp95J_8X5Ie=B49J&P(h*gLfCZ&H z1}{sFspcn9$6;dqIPu``CbRSZ6MMVkde{Z~9Do49d&k<)Xmt3A+K!3W!UTg>QQ1EIq`nR8=%h5*c~4+Tjaw zn#)o0YKJNW<@q7RQww9U)aI6;1~p!JBVLL}`c_`SKc#7WrN#TGo=iHj4fv*@g+;%x z-Wmu~XJHIyH1j~Gl|v1@cN~CFcF4YE8UZYRVq$=xS7dUhb8c7OnKvZ&c5NCO!5Lsk zpUwv1!iKhc8rV7I&3)V$k^;<{ymao?AkBb6a8RgdZ39^D!7}6GdJWIW12c+so(MJt z=N^b{$?UQSawx=<_@z0LCX;y=)F&@9yx|DPGDHR}MZDk=9lvvrhP+hm>Bx0PG7}y9 z6DRCfHX09hOhO|BPzlpH(fWmEm1=p-^y5fP%Oz#3fBl@UsFmki$WU4%7HCM?#s$6D z3D!4=E8L+HJJyA2n-9z@T7IEa1v#5D`BgF~SyDs2(OChl_H4HMI@<$O?msmL&F%=c z(^MR~p{Z(s9UaN82KY%UU*@g& zE%d8iEd9M=7qZj@`#Y*Cxm>ZVVHx~=vfY^(6iR<(bbRUi{m?u6*6S&w!}-1>0HC~9 zl85dAFj%j(mrvnG4h;gxJZT;o;A567G!=^CQsiPpkRdYu`V(g5! z014WcBqR!3N&L|Xxp^HoXn|LwY=`R9-Xf~7lQ`(it3@~6@C^g(OC8VpB%CNfUM*ds zQIU}#U#L7=RJm~=3ie|(rPfuk9fl=s!syH)yPycZU0yFd)#bNKNn?rMW~mkqUlUCd z)giU%K-4Uzi)$+Lvtg8oYdfdNz~P!^)5wxS3akn3C^O^kZoZ!0d9zxQDP5gIZ&a|TLo{&Zbupy_Q@4|88XONjh6iFbRUw?H zq+V^rtTSDaz}JjcS&6XcKAUpLSr_h>3Q;+%qsAUU<7b(ofN->>E&Frqcbt;p6sMTE^(Z?t@=ww1Qv%KFzPfhyaAFzCI;4j0=w z@)5&I{4885OSYmtBQBS5BcU>CxSC;6to7pF&qtEddp4FV#cX!$yfn&*bVj%zLIKS< zBeRZLs0?$Ut9;rfUD@s#o>Th<0 zOqKGTch$jb?8}%44V~)UpDI-btYylQ@x9Qt<^wC^5wI#QbF-9e8EW$t-imsOYeTKG94yO-OF76thqmRAn%3b}2O_Vz& zm%)=5(XN`X+Bxe*pXow(SN)FT#m`Rqa)k${!5?U##6Q9Q-x6#An!8tm_WF5q)o+)@ z`5*Z<$s=4mOJ{{OhO&}J|8Cn}#0)!+5<1DUsn{WQU3%EJ`dfph$@{X&_i<@Qc(i(H zvc^=hLaodCU6%C0QuN4bhHQxEhF#;q;zxwkf1a&PsmjAHOUor&WkfpQ&k?ZFwX8BqJ=;`Tz#@%0A>?B-v*E%$r}T>bNk9E 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¬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 Zs-;Q@GBEU(Q#ZUq4luV_1~~}c{{a$q^}GN8 literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.md5 new file mode 100644 index 000000000000..eff56f281fbd --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.md5 @@ -0,0 +1 @@ +e158df8d1a539cc6482567f9689cc36f \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.sha1 new file mode 100644 index 000000000000..953f76d88838 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.jar.sha1 @@ -0,0 +1 @@ +56559396674aacd498c298964b691db0177027c0 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom new file mode 100644 index 000000000000..55baddfd90f2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom @@ -0,0 +1,61 @@ + + + plexus + org.codehaus.plexus + 1.0.11 + ../pom/pom.xml + + 4.0.0 + plexus-utils + Plexus Common Utilities + 1.4.5 + http://plexus.codehaus.org/plexus-utils + + + + maven-compiler-plugin + + + 1.3 + 1.3 + + + + maven-surefire-plugin + + + true + + org/codehaus/plexus/util/FileBasedTestCase.java + **/Test*.java + + + + JAVA_HOME + ${JAVA_HOME} + + + M2_HOME + ${M2_HOME} + + + + + + + + scm:svn:http://svn.codehaus.org/plexus/plexus-utils/tags/plexus-utils-1.4.5 + scm:svn:https://svn.codehaus.org/plexus/plexus-utils/tags/plexus-utils-1.4.5 + http://fisheye.codehaus.org/browse/plexus/plexus-utils/tags/plexus-utils-1.4.5 + + + + + maven-javadoc-plugin + + + maven-jxr-plugin + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.md5 new file mode 100644 index 000000000000..905f70a9b275 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.md5 @@ -0,0 +1 @@ +fccab705018ed5559df9f8e815b79aaa \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.sha1 new file mode 100644 index 000000000000..247cd9435608 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.4.5/plexus-utils-1.4.5.pom.sha1 @@ -0,0 +1 @@ +0bdc8a7fbce7d9007a93d289a029b43e1196d85c \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom new file mode 100644 index 000000000000..ee904a03dfcc --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom @@ -0,0 +1,273 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.10 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus User List + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://archive.plexus.codehaus.org/user + + + Plexus Developer List + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://archive.plexus.codehaus.org/dev + + + Plexus Announce List + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://archive.plexus.codehaus.org/announce + + + Plexus Commit List + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://archive.plexus.codehaus.org/scm + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + codehaus.snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + Andrew Williams + handyande + andy@handyande.co.uk + + Developer + + + + Rahul Thakur + rahul + rahul.thakur.xdev@gmail.com + + Developer + + + + Joakim Erdfelt + joakime + joakim@erdfelt.com + + Developer + + + + Olivier Lamy + olamy + olamy@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/pom/tags/plexus-1.0.10 + scm:svn:https://svn.codehaus.org/plexus/pom/tags/plexus-1.0.10 + http://fisheye.codehaus.org/browse/plexus/pom/tags/plexus-1.0.10 + + + Codehaus + http://www.codehaus.org/ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.4 + 1.4 + + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-2 + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.md5 new file mode 100644 index 000000000000..7ae43d7e91ab --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.md5 @@ -0,0 +1 @@ +6ab958c91424c0d7c3a2cc861867905e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.sha1 new file mode 100644 index 000000000000..8ed366f9891d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.10/plexus-1.0.10.pom.sha1 @@ -0,0 +1 @@ +039c3f6a3cbe1f9e7b4a3309d9d7062b6e390fa7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom new file mode 100644 index 000000000000..1f491ae4f742 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom @@ -0,0 +1,308 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.11 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + The Apache Software License, Version 2.0 + http://www.apache.org/licenses/LICENSE-2.0.txt + repo + + + + + Plexus User List + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://archive.plexus.codehaus.org/user + + + Plexus Developer List + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://archive.plexus.codehaus.org/dev + + + Plexus Announce List + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://archive.plexus.codehaus.org/announce + + + Plexus Commit List + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://archive.plexus.codehaus.org/scm + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + codehaus.snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + Andrew Williams + handyande + andy@handyande.co.uk + + Developer + + + + Rahul Thakur + rahul + rahul.thakur.xdev@gmail.com + + Developer + + + + Joakim Erdfelt + joakime + joakim@erdfelt.com + + Developer + + + + Olivier Lamy + olamy + olamy@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/pom/trunk/ + scm:svn:https://svn.codehaus.org/plexus/pom/trunk/ + http://fisheye.codehaus.org/browse/plexus/pom/trunk/ + + + Codehaus + http://www.codehaus.org/ + + + + + org.apache.maven.plugins + maven-compiler-plugin + + 1.4 + 1.4 + + + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-2 + + + + + + maven-release-plugin + + deploy + + + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.md5 new file mode 100644 index 000000000000..2cabbba02bdc --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.md5 @@ -0,0 +1 @@ +bdf8dcfe0877af604f7e19e9ffdf260b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.sha1 new file mode 100644 index 000000000000..1ba2b3afc2ee --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.11/plexus-1.0.11.pom.sha1 @@ -0,0 +1 @@ +4693d4512d50c5159bef1c49def1d2690a327c30 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom new file mode 100644 index 000000000000..0867e8bc0eee --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom @@ -0,0 +1,205 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.4 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus Developer List + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/pipermail/plexus-dev/ + + + + + + repo1 + Maven Central Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/to-ibiblio/maven2 + + + snapshots + Maven Central Development Repository + scp://repo1.maven.org/home/projects/maven/repository-staging/snapshots/maven2 + + + + + snapshots + Maven Snapshot Development Repository + http://snapshots.maven.codehaus.org/maven2 + + false + + + + + + snapshots-plugins + Maven Snapshot Plugins Development Repository + http://snapshots.maven.codehaus.org/maven2 + + false + + + + + + + jvanzyl + Jason van Zyl + jason@zenplex.com + Zenplex + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstøl + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:svn://svn.codehaus.org/plexus/scm/trunk/ + scm:svn:https://svn.codehaus.org/plexus/trunk + + + Codehaus + http://www.codehaus.org/ + + + plexus-appserver + plexus-archetypes + plexus-components + plexus-component-factories + plexus-containers + plexus-logging + plexus-maven-plugin + plexus-services + plexus-tools + plexus-utils + + + + + org.apache.maven.plugins + maven-release-plugin + + https://svn.codehaus.org/plexus/tags + + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 new file mode 100644 index 000000000000..ec5562d8b81d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.md5 @@ -0,0 +1 @@ +2e97f3a7666e337ce5d2d98b9c384cae \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 new file mode 100644 index 000000000000..456d534766a4 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.4/plexus-1.0.4.pom.sha1 @@ -0,0 +1 @@ +06f66b2f7d2eef1d805c11bca91c89984cda4137 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom new file mode 100644 index 000000000000..c6afe11423ef --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom @@ -0,0 +1,259 @@ + + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.8 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus Developer List + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/mailman/listinfo/plexus-dev + http://lists.codehaus.org/pipermail/plexus-dev/ + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + apache-snapshots + Snapshot repository + http://people.apache.org/maven-snapshot-repository + + false + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/trunk/ + scm:svn:https://svn.codehaus.org/plexus/trunk + + + Codehaus + http://www.codehaus.org/ + + + + plexus-archetypes + plexus-examples + plexus-components + plexus-component-factories + plexus-containers + plexus-logging + plexus-maven-plugin + plexus-tools + plexus-utils + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-1 + + + + + org.apache.maven.plugins + maven-release-plugin + + https://svn.codehaus.org/plexus/tags + + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 new file mode 100644 index 000000000000..e0d40fcdad43 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.md5 @@ -0,0 +1 @@ +2da4039a1c4c959c75d3e6126f2029cf \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 new file mode 100644 index 000000000000..5234d5638aaf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.8/plexus-1.0.8.pom.sha1 @@ -0,0 +1 @@ +9e7c8432829962afe796b32587c1bfa841a317d5 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom new file mode 100644 index 000000000000..6f4e50097db1 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom @@ -0,0 +1,257 @@ + + 4.0.0 + org.codehaus.plexus + plexus + pom + Plexus + 1.0.9 + + + + mail + +
dev@plexus.codehaus.org
+
+
+ + irc + + irc.codehaus.org + 6667 + #plexus + + +
+
+ 2001 + + + Plexus User List + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/user%40plexus.codehaus.org + http://archive.plexus.codehaus.org/user + + + Plexus Developer List + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/dev%40plexus.codehaus.org + http://archive.plexus.codehaus.org/dev + + + Plexus Announce List + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/announce%40plexus.codehaus.org + http://archive.plexus.codehaus.org/announce + + + Plexus Commit List + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://xircles.codehaus.org/manage_email/scm%40plexus.codehaus.org + http://archive.plexus.codehaus.org/scm + + + + JIRA + http://jira.codehaus.org/browse/PLX + + + + + codehaus.org + Plexus Central Repository + dav:https://dav.codehaus.org/repository/plexus + + + codehaus.org + Plexus Central Development Repository + dav:https://dav.codehaus.org/snapshots.repository/plexus + + + codehaus.org + dav:https://dav.codehaus.org/plexus + + + + + apache-snapshots + Snapshot repository + http://people.apache.org/maven-snapshot-repository + + false + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + codehaus-snapshots + Codehaus Snapshot Development Repository + http://snapshots.repository.codehaus.org + + false + + + + + + + jvanzyl + Jason van Zyl + jason@maven.org + + Developer + Release Manager + + + + kaz + Pete Kazmier + + + + Developer + + + + jtaylor + James Taylor + james@jamestaylor.org + + + Developer + + + + dandiep + Dan Diephouse + dan@envoisolutions.com + Envoi solutions + + Developer + + + + kasper + Kasper Nielsen + apache@kav.dk + + + Developer + + + + bwalding + Ben Walding + bwalding@codehaus.org + Walding Consulting Services + + Developer + + + + mhw + Mark Wilkinson + mhw@kremvax.net + + Developer + + + + michal + Michal Maczka + mmaczka@interia.pl + + Developer + + + + evenisse + Emmanuel Venisse + evenisse@codehaus.org + + Developer + + + + Trygve Laugstol + trygvis + trygvis@codehaus.org + + Developer + + + + Kenney Westerhof + kenney + kenney@codehaus.org + + Developer + + + + Carlos Sanchez + carlos + carlos@codehaus.org + + Developer + + + + Brett Porter + brett + brett@codehaus.org + + Developer + + + + John Casey + jdcasey + jdcasey@codehaus.org + + Developer + + + + Andrew Williams + handyande + andy@handyande.co.uk + + Developer + + + + + + junit + junit + 4.13.1 + test + + + + scm:svn:http://svn.codehaus.org/plexus/pom/tags/plexus-1.0.9 + scm:svn:https://svn.codehaus.org/plexus/pom/tags/plexus-1.0.9 + http://fisheye.codehaus.org/browse/plexus/pom/tags/plexus-1.0.9 + + + Codehaus + http://www.codehaus.org/ + + + + + org.apache.maven.wagon + wagon-webdav + 1.0-beta-1 + + + +
diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 new file mode 100644 index 000000000000..3910bf8b1725 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.md5 @@ -0,0 +1 @@ +acf338e422e5c0d9c6242e4f21e63dc9 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 new file mode 100644 index 000000000000..df40a701c140 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus/1.0.9/plexus-1.0.9.pom.sha1 @@ -0,0 +1 @@ +89d241b1e5ee6a72d3dd95d9eb90f635deebcdb2 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc-resources.jar.lastUpdated b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc-resources.jar.lastUpdated new file mode 100644 index 000000000000..d326d8b4f020 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc-resources.jar.lastUpdated @@ -0,0 +1,4 @@ +#NOTE: This is a Maven Resolver internal implementation file, its format can be changed without prior notice. +#Wed Jan 05 14:06:51 CET 2022 +https\://repo.maven.apache.org/maven2/.lastUpdated=1641388011987 +https\://repo.maven.apache.org/maven2/.error= diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar new file mode 100644 index 0000000000000000000000000000000000000000..eb935e035fa53070e4703ad908f46726469cd610 GIT binary patch literal 242519 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
>s+VFKZ$M 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 literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar.sha1 new file mode 100644 index 000000000000..304c4b0f90b2 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-javadoc.jar.sha1 @@ -0,0 +1 @@ +ad09811315f1d4f5756986575b0ea16b99cd686f \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar new file mode 100644 index 0000000000000000000000000000000000000000..c3c110b4dab6b916fc1ab30eaff8e16391d90d50 GIT binary patch literal 32624 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 literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar.sha1 new file mode 100644 index 000000000000..ce64bf95e5c8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3-sources.jar.sha1 @@ -0,0 +1 @@ +1dc37250fbc78e23a65a67fbbaf71d2e9cbc3c0b \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar new file mode 100644 index 0000000000000000000000000000000000000000..9d5fe16e3dd37ebe79a36f61f5d0e1a69a653a8a GIT binary patch literal 45024 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 UgpPtD2z>DYYp}SJr5?)v0beu;=l}o! literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar.sha1 new file mode 100644 index 000000000000..1085ece454c9 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.jar.sha1 @@ -0,0 +1 @@ +42a25dc3219429f0e5d060061f71acb49bf010a0 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom new file mode 100644 index 000000000000..0721781c99a0 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom @@ -0,0 +1,18 @@ + + + 4.0.0 + + + org.hamcrest + hamcrest-parent + 1.3 + + + hamcrest-core + jar + Hamcrest Core + + This is the core API of hamcrest matcher framework to be used by third-party framework providers. This includes the a foundation set of matcher implementations for common operations. + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom.sha1 new file mode 100644 index 000000000000..53d5f15b56c5 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-core/1.3/hamcrest-core-1.3.pom.sha1 @@ -0,0 +1 @@ +872e413497b906e7c9fa85ccc96046c5d1ef7ece \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom new file mode 100644 index 000000000000..ae4b4b4df8dd --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom @@ -0,0 +1,72 @@ + + + 4.0.0 + + org.hamcrest + hamcrest-parent + 1.3 + pom + + Hamcrest Maven Parent + https://github.com/hamcrest/JavaHamcrest + General parent POM for all hamcrest libraries. + + + + New BSD License + http://www.opensource.org/licenses/bsd-license.php + repo + + + + + https://github.com/hamcrest/JavaHamcrest + scm:git:git@github.com:hamcrest/JavaHamcrest.git + + + + + joe.walnes + Joe Walnes + + Developer + + + + nat.pryce + Nat Pryce + + Developer + + + + smgfreeman + Steve Freeman + + Developer + + + + neildunn + Neil Dunn + + Developer + + + + scarytom + Tom Denley + + Developer + + + + + + hamcrest-core + hamcrest-generator + hamcrest-library + hamcrest-integration + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom.sha1 new file mode 100644 index 000000000000..c5c5f185ebd8 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/hamcrest/hamcrest-parent/1.3/hamcrest-parent-1.3.pom.sha1 @@ -0,0 +1 @@ +80391bd32bfa4837a15215d5e9f07c60555c379a \ No newline at end of file diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java index ffb9ea830165..44bed45cd8d1 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/MavenCli.java @@ -72,6 +72,7 @@ import org.apache.maven.toolchain.building.DefaultToolchainsBuildingRequest; import org.apache.maven.toolchain.building.ToolchainsBuilder; import org.apache.maven.toolchain.building.ToolchainsBuildingResult; +import org.apache.maven.toolchain.model.PersistedToolchains; import org.codehaus.plexus.ContainerConfiguration; import org.codehaus.plexus.DefaultContainerConfiguration; import org.codehaus.plexus.DefaultPlexusContainer; @@ -1333,7 +1334,7 @@ void toolchains( CliRequest cliRequest ) eventSpyDispatcher.onEvent( toolchainsResult ); executionRequestPopulator.populateFromToolchains( cliRequest.request, - toolchainsResult.getEffectiveToolchains() ); + new PersistedToolchains( toolchainsResult.getEffectiveToolchains() ) ); if ( !toolchainsResult.getProblems().isEmpty() && slf4jLogger.isWarnEnabled() ) { diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java index ef0c55360c08..5bdc8895b41a 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/configuration/SettingsXmlConfigurationProcessor.java @@ -35,11 +35,11 @@ import org.apache.maven.cli.CliRequest; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequestPopulationException; -import org.apache.maven.settings.Mirror; -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.api.settings.Mirror; +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.SettingsUtils; import org.apache.maven.settings.building.DefaultSettingsBuildingRequest; import org.apache.maven.settings.building.SettingsBuilder; @@ -188,9 +188,7 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques for ( Server server : settings.getServers() ) { - server = server.clone(); - - request.addServer( server ); + request.addServer( new org.apache.maven.settings.Server( server ) ); } // @@ -212,9 +210,7 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques continue; } - proxy = proxy.clone(); - - request.addProxy( proxy ); + request.addProxy( new org.apache.maven.settings.Proxy( proxy ) ); } // @@ -227,14 +223,12 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques for ( Mirror mirror : settings.getMirrors() ) { - mirror = mirror.clone(); - - request.addMirror( mirror ); + request.addMirror( new org.apache.maven.settings.Mirror( mirror ) ); } request.setActiveProfiles( settings.getActiveProfiles() ); - for ( org.apache.maven.settings.Profile rawProfile : settings.getProfiles() ) + for ( org.apache.maven.api.settings.Profile rawProfile : settings.getProfiles() ) { request.addProfile( SettingsUtils.convertFromSettingsProfile( rawProfile ) ); @@ -245,8 +239,8 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques { try { - request.addRemoteRepository( - MavenRepositorySystem.buildArtifactRepository( remoteRepository ) ); + request.addRemoteRepository( MavenRepositorySystem.buildArtifactRepository( + new org.apache.maven.settings.Repository( remoteRepository ) ) ); } catch ( InvalidRepositoryException e ) { @@ -259,8 +253,8 @@ private MavenExecutionRequest populateFromSettings( MavenExecutionRequest reques { try { - request.addPluginArtifactRepository( - MavenRepositorySystem.buildArtifactRepository( pluginRepository ) ); + request.addPluginArtifactRepository( MavenRepositorySystem.buildArtifactRepository( + new org.apache.maven.settings.Repository( pluginRepository ) ) ); } catch ( InvalidRepositoryException e ) { diff --git a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java index 74570eb38be7..a109f1aa566f 100644 --- a/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java +++ b/maven-embedder/src/main/java/org/apache/maven/cli/internal/BootstrapCoreExtensionManager.java @@ -33,7 +33,7 @@ import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.extension.internal.CoreExtensionEntry; import org.apache.maven.internal.aether.DefaultRepositorySystemSessionFactory; -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Plugin; import org.apache.maven.plugin.PluginResolutionException; import org.apache.maven.plugin.internal.DefaultPluginDependenciesResolver; import org.codehaus.plexus.DefaultPlexusContainer; @@ -144,13 +144,15 @@ private List resolveExtension( CoreExtension extension, RepositorySyst * resolveCoreExtension method which uses a CoreExtension * object instead of a Plugin as this makes no sense. */ - Plugin plugin = new Plugin(); - plugin.setGroupId( interpolator.interpolate( extension.getGroupId() ) ); - plugin.setArtifactId( interpolator.interpolate( extension.getArtifactId() ) ); - plugin.setVersion( interpolator.interpolate( extension.getVersion() ) ); + Plugin plugin = Plugin.newBuilder() + .groupId( interpolator.interpolate( extension.getGroupId() ) ) + .artifactId( interpolator.interpolate( extension.getArtifactId() ) ) + .version( interpolator.interpolate( extension.getVersion() ) ) + .build(); DependencyNode root = pluginDependenciesResolver - .resolveCoreExtension( plugin, dependencyFilter, repositories, repoSession ); + .resolveCoreExtension( new org.apache.maven.model.Plugin( plugin ), + dependencyFilter, repositories, repoSession ); PreorderNodeListGenerator nlg = new PreorderNodeListGenerator(); root.accept( nlg ); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java index e4154612817b..b830132f3531 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java @@ -25,7 +25,7 @@ import java.util.function.BiFunction; import java.util.function.Function; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.transform.BuildToRawPomXMLFilterFactory; import org.apache.maven.model.transform.RelativeProject; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index de84b90de03f..1f51c7f924db 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -19,11 +19,13 @@ * under the License. */ -import static org.apache.maven.model.building.Result.error; -import static org.apache.maven.model.building.Result.newResult; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; import java.io.File; import java.io.IOException; +import java.lang.reflect.Field; import java.nio.file.Files; import java.nio.file.Path; import java.util.ArrayList; @@ -39,29 +41,26 @@ import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; - -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; - +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginManagement; +import org.apache.maven.api.model.Profile; +import org.apache.maven.api.model.Repository; import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.building.Source; import org.apache.maven.feature.Features; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.Profile; -import org.apache.maven.model.Repository; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.composition.DependencyManagementImporter; @@ -71,7 +70,6 @@ import org.apache.maven.model.io.ModelReader; import org.apache.maven.model.management.DependencyManagementInjector; import org.apache.maven.model.management.PluginManagementInjector; -import org.apache.maven.model.merge.ModelMerger; import org.apache.maven.model.normalization.ModelNormalizer; import org.apache.maven.model.path.ModelPathTranslator; import org.apache.maven.model.path.ModelUrlNormalizer; @@ -89,17 +87,22 @@ import org.apache.maven.model.resolution.UnresolvableModelException; import org.apache.maven.model.resolution.WorkspaceModelResolver; import org.apache.maven.model.superpom.SuperPomProvider; +import org.apache.maven.model.v4.ModelMerger; import org.apache.maven.model.validation.ModelValidator; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.MapBasedValueSource; import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.eclipse.sisu.Nullable; +import static org.apache.maven.model.building.Result.error; +import static org.apache.maven.model.building.Result.newResult; + /** * @author Benjamin Bentmann */ @Named @Singleton +@SuppressWarnings( {"checkstyle:JavaDocMethod", "checkstyle:HiddenField", "checkstyle:ParameterNumber" } ) public class DefaultModelBuilder implements ModelBuilder { @@ -444,11 +447,11 @@ protected ModelBuildingResult build( ModelBuildingRequest request, Collection interpolatedActivations = getProfileActivations( inputModel, false ); - injectProfileActivations( inputModel, interpolatedActivations ); + Map interpolatedActivations = getProfileActivations( inputModel ); + inputModel = injectProfileActivations( inputModel, interpolatedActivations ); // profile injection for ( Profile activeProfile : activePomProfiles ) { - profileInjector.injectProfile( inputModel, activeProfile, request, problems ); + inputModel = profileInjector.injectProfile( inputModel, activeProfile, request, problems ); } for ( Profile activeProfile : activeExternalProfiles ) { - profileInjector.injectProfile( inputModel, activeProfile, request, problems ); + inputModel = profileInjector.injectProfile( inputModel, activeProfile, request, problems ); } + + return inputModel; } @SuppressWarnings( "checkstyle:methodlength" ) @@ -559,39 +563,39 @@ private Model readEffectiveModel( final ModelBuildingRequest request, final Defa profileActivationContext, problems ); result.setActivePomProfiles( modelId, activePomProfiles ); - Model tmpModel = rawModel.clone(); + Model tmpModel = rawModel; problems.setSource( tmpModel ); // model normalization - modelNormalizer.mergeDuplicates( tmpModel, request, problems ); + tmpModel = modelNormalizer.mergeDuplicates( tmpModel, request, problems ); profileActivationContext.setProjectProperties( tmpModel.getProperties() ); Map interpolatedActivations = getInterpolatedActivations( rawModel, profileActivationContext, problems ); - injectProfileActivations( tmpModel, interpolatedActivations ); + tmpModel = injectProfileActivations( tmpModel, interpolatedActivations ); // profile injection for ( Profile activeProfile : result.getActivePomProfiles( modelId ) ) { - profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); + tmpModel = profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); } if ( currentData == resultData ) { for ( Profile activeProfile : activeExternalProfiles ) { - profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); + tmpModel = profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); } result.setEffectiveModel( tmpModel ); } - lineage.add( tmpModel ); - if ( currentData == superData ) { + lineage.add( tmpModel ); + break; } @@ -620,17 +624,21 @@ else if ( !parentIds.add( parentData.getId() ) ) } else { + if ( !Objects.equals( tmpModel.getParent().getVersion(), parentData.getVersion() ) ) + { +// tmpModel = tmpModel.withParent( tmpModel.getParent().withVersion( parentData.getVersion() ) ); + } currentData = parentData; } + + lineage.add( tmpModel ); } problems.setSource( result.getRawModel() ); checkPluginVersions( lineage, request, problems ); // inheritance assembly - assembleInheritance( lineage, request, problems ); - - Model resultModel = lineage.get( 0 ); + Model resultModel = assembleInheritance( lineage, request, problems ); // consider caching inherited model @@ -641,7 +649,7 @@ else if ( !parentIds.add( parentData.getId() ) ) resultModel = interpolateModel( resultModel, request, problems ); // url normalization - modelUrlNormalizer.normalize( resultModel, request ); + resultModel = modelUrlNormalizer.normalize( resultModel, request ); result.setEffectiveModel( resultModel ); @@ -655,19 +663,23 @@ private Map getInterpolatedActivations( Model rawModel, DefaultProfileActivationContext context, DefaultModelProblemCollector problems ) { - Map interpolatedActivations = getProfileActivations( rawModel, true ); - for ( Activation activation : interpolatedActivations.values() ) + Map interpolatedActivations = getProfileActivations( rawModel ); + for ( Map.Entry entry : interpolatedActivations.entrySet() ) { + Activation activation = entry.getValue(); if ( activation.getFile() != null ) { - replaceWithInterpolatedValue( activation.getFile(), context, problems ); + Activation value = activation.withFile( + replaceWithInterpolatedValue( activation.getFile(), context, problems ) ); + entry.setValue( value ); } } return interpolatedActivations; } - private void replaceWithInterpolatedValue( ActivationFile activationFile, ProfileActivationContext context, - DefaultModelProblemCollector problems ) + private ActivationFile replaceWithInterpolatedValue( ActivationFile activationFile, + ProfileActivationContext context, + DefaultModelProblemCollector problems ) { try { @@ -675,13 +687,13 @@ private void replaceWithInterpolatedValue( ActivationFile activationFile, Profil { String path = activationFile.getExists(); String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context ); - activationFile.setExists( absolutePath ); + return activationFile.withExists( absolutePath ); } else if ( isNotEmpty( activationFile.getMissing() ) ) { String path = activationFile.getMissing(); String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context ); - activationFile.setMissing( absolutePath ); + return activationFile.withMissing( absolutePath ); } } catch ( InterpolationException e ) @@ -694,6 +706,7 @@ else if ( isNotEmpty( activationFile.getMissing() ) ) activationFile.getLocation( isNotEmpty( activationFile.getExists() ) ? "exists" : "missing" ) ) .setException( e ) ); } + return activationFile; } private static boolean isNotEmpty( String string ) @@ -722,10 +735,12 @@ private ModelBuildingResult build( final ModelBuildingRequest request, final Mod problems.setRootModel( resultModel ); // model path translation - modelPathTranslator.alignToBaseDirectory( resultModel, resultModel.getProjectDirectory(), request ); + Path projectDirectory = resultModel.getProjectDirectory(); + resultModel = modelPathTranslator.alignToBaseDirectory( resultModel, + projectDirectory != null ? projectDirectory.toFile() : null, request ); // plugin management injection - pluginManagementInjector.injectManagement( resultModel, request, problems ); + resultModel = pluginManagementInjector.injectManagement( resultModel, request, problems ); fireEvent( resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED ); @@ -737,32 +752,34 @@ private ModelBuildingResult build( final ModelBuildingRequest request, final Mod } // lifecycle bindings injection - lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems ); + resultModel = lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems ); } // dependency management import - importDependencyManagement( resultModel, request, problems, imports ); + resultModel = importDependencyManagement( resultModel, request, problems, imports ); // dependency management injection - dependencyManagementInjector.injectManagement( resultModel, request, problems ); + resultModel = dependencyManagementInjector.injectManagement( resultModel, request, problems ); - modelNormalizer.injectDefaultValues( resultModel, request, problems ); + resultModel = modelNormalizer.injectDefaultValues( resultModel, request, problems ); if ( request.isProcessPlugins() ) { // reports configuration - reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); + resultModel = reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); // reports conversion to decoupled site plugin - reportingConverter.convertReporting( resultModel, request, problems ); + resultModel = reportingConverter.convertReporting( resultModel, request, problems ); // plugins configuration - pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); + resultModel = pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); } // effective model validation modelValidator.validateEffectiveModel( resultModel, request, problems ); + result.setEffectiveModel( resultModel ); + if ( hasModelErrors( problems ) ) { throw problems.newModelBuildingException(); @@ -845,7 +862,8 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req InputSource source; if ( request.isLocationTracking() ) { - source = (InputSource) options.computeIfAbsent( ModelProcessor.INPUT_SOURCE, k -> new InputSource() ); + source = (InputSource) options.computeIfAbsent( ModelProcessor.INPUT_SOURCE, + k -> new InputSource( null, modelSource.getLocation() ) ); } else { @@ -883,8 +901,17 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req if ( source != null ) { - source.setModelId( ModelProblemUtils.toId( model ) ); - source.setLocation( modelSource.getLocation() ); + try + { + Field field = InputSource.class.getDeclaredField( "modelId" ); + field.setAccessible( true ); + field.set( source, ModelProblemUtils.toId( model ) ); + } + catch ( Throwable t ) + { + // TODO: use a lazy source ? + throw new IllegalStateException( "Unable to set modelId on InputSource", t ); + } } } catch ( ModelParseException e ) @@ -916,7 +943,7 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req if ( modelSource instanceof FileModelSource ) { - model.setPomFile( ( (FileModelSource) modelSource ).getFile() ); + model = Model.newBuilder( model ).pomFile( ( (FileModelSource) modelSource ).getFile().toPath() ).build(); } problems.setSource( model ); @@ -963,7 +990,7 @@ private Model readRawModel( ModelBuildingRequest request, DefaultModelProblemCol // rawModel with locationTrackers, required for proper feedback during validations // Apply enriched data - modelMerger.merge( rawModel, transformedFileModel, false, null ); + rawModel = modelMerger.merge( rawModel, transformedFileModel, false, null ); } catch ( IOException e ) { @@ -976,7 +1003,7 @@ else if ( request.getFileModel() == null ) } else { - rawModel = request.getFileModel().clone(); + rawModel = request.getFileModel(); } modelValidator.validateRawModel( rawModel, request, problems ); @@ -1113,18 +1140,19 @@ private void checkPluginVersions( List lineage, ModelBuildingRequest requ } } - private void assembleInheritance( List lineage, ModelBuildingRequest request, + private Model assembleInheritance( List lineage, ModelBuildingRequest request, ModelProblemCollector problems ) { + Model parent = lineage.get( lineage.size() - 1 ); for ( int i = lineage.size() - 2; i >= 0; i-- ) { - Model parent = lineage.get( i + 1 ); Model child = lineage.get( i ); - inheritanceAssembler.assembleModelInheritance( child, parent, request, problems ); + parent = inheritanceAssembler.assembleModelInheritance( child, parent, request, problems ); } + return parent; } - private Map getProfileActivations( Model model, boolean clone ) + private Map getProfileActivations( Model model ) { Map activations = new HashMap<>(); for ( Profile profile : model.getProfiles() ) @@ -1136,19 +1164,15 @@ private Map getProfileActivations( Model model, boolean clon continue; } - if ( clone ) - { - activation = activation.clone(); - } - activations.put( profile.getId(), activation ); } return activations; } - private void injectProfileActivations( Model model, Map activations ) + private Model injectProfileActivations( Model model, Map activations ) { + List newProfiles = null; for ( Profile profile : model.getProfiles() ) { Activation activation = profile.getActivation(); @@ -1159,30 +1183,44 @@ private void injectProfileActivations( Model model, Map acti } // restore activation - profile.setActivation( activations.get( profile.getId() ) ); + if ( newProfiles == null ) + { + newProfiles = new ArrayList<>( model.getProfiles() ); + } + int idx = model.getProfiles().indexOf( profile ); + Profile newProfile = Profile.newBuilder( profile ). + activation( activations.get( profile.getId() ) ).build(); + newProfiles.set( idx, newProfile ); } + return Model.newBuilder( model ).profiles( newProfiles ).build(); } private Model interpolateModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { // save profile activations before interpolation, since they are evaluated with limited scope - Map originalActivations = getProfileActivations( model, true ); + Map originalActivations = getProfileActivations( model ); - Model interpolatedModel = - modelInterpolator.interpolateModel( model, model.getProjectDirectory(), request, problems ); + Path projectDir = model.getProjectDirectory(); + Model interpolatedModel = modelInterpolator.interpolateModel( + model, projectDir != null ? projectDir.toFile() : null, request, problems ); if ( interpolatedModel.getParent() != null ) { StringSearchInterpolator ssi = new StringSearchInterpolator(); ssi.addValueSource( new MapBasedValueSource( request.getUserProperties() ) ); - ssi.addValueSource( new MapBasedValueSource( model.getProperties() ) ); - ssi.addValueSource( new MapBasedValueSource( request.getSystemProperties() ) ); try { - String interpolated = ssi.interpolate( interpolatedModel.getParent().getVersion() ); - interpolatedModel.getParent().setVersion( interpolated ); + String parentVersion = interpolatedModel.getParent().getVersion(); + + String interpolated = ssi.interpolate( parentVersion ); + + if ( !parentVersion.equals( interpolated ) ) + { + interpolatedModel = interpolatedModel.withParent( + interpolatedModel.getParent().withVersion( interpolated ) ); + } } catch ( Exception e ) { @@ -1193,10 +1231,8 @@ private Model interpolateModel( Model model, ModelBuildingRequest request, Model + " on class: " ).setException( e ); problems.add( mpcr ); } - - } - interpolatedModel.setPomFile( model.getPomFile() ); + interpolatedModel = interpolatedModel.withPomFile( model.getPomFile() ); // restore profiles with file activation to their value before full interpolation injectProfileActivations( model, originalActivations ); @@ -1271,7 +1307,7 @@ private ModelData readParentLocally( Model childModel, Source childSource, Model { return null; } - candidateSource = new FileModelSource( candidateModel.getPomFile() ); + candidateSource = new FileModelSource( candidateModel.getPomFile().toFile() ); } // @@ -1406,9 +1442,10 @@ private ModelData readParentExternally( Model childModel, ModelBuildingRequest r ModelProblemUtils.toSourceHint( childModel ) ) ); ModelSource modelSource; + AtomicReference modified = new AtomicReference<>(); try { - modelSource = modelResolver.resolveModel( parent ); + modelSource = modelResolver.resolveModel( parent, modified ); } catch ( UnresolvableModelException e ) { @@ -1441,6 +1478,12 @@ private ModelData readParentExternally( Model childModel, ModelBuildingRequest r throw problems.newModelBuildingException(); } + if ( modified.get() != null ) + { + parent = modified.get(); + childModel = childModel.withParent( parent ); + } + int validationLevel = Math.min( request.getValidationLevel(), ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 ); ModelBuildingRequest lenientRequest = new DefaultModelBuildingRequest( request ) .setValidationLevel( validationLevel ) @@ -1481,17 +1524,17 @@ private ModelData readParentExternally( Model childModel, ModelBuildingRequest r private Model getSuperModel() { - return superPomProvider.getSuperModel( "4.0.0" ).clone(); + return superPomProvider.getSuperModel( "4.0.0" ); } - private void importDependencyManagement( Model model, ModelBuildingRequest request, + private Model importDependencyManagement( Model model, ModelBuildingRequest request, DefaultModelProblemCollector problems, Collection importIds ) { DependencyManagement depMgmt = model.getDependencyManagement(); if ( depMgmt == null ) { - return; + return model; } String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion(); @@ -1500,6 +1543,8 @@ private void importDependencyManagement( Model model, ModelBuildingRequest reque List importMgmts = null; + List newDependencies = null; + for ( Iterator it = depMgmt.getDependencies().iterator(); it.hasNext(); ) { Dependency dependency = it.next(); @@ -1509,7 +1554,11 @@ private void importDependencyManagement( Model model, ModelBuildingRequest reque continue; } - it.remove(); + if ( newDependencies == null ) + { + newDependencies = new ArrayList<>( depMgmt.getDependencies() ); + } + newDependencies.remove( dependency ); DependencyManagement importMgmt = loadDependencyManagement( model, request, problems, dependency, importIds ); @@ -1525,9 +1574,14 @@ private void importDependencyManagement( Model model, ModelBuildingRequest reque } } + if ( newDependencies != null ) + { + model = model.withDependencyManagement( depMgmt.withDependencies( newDependencies ) ); + } + importIds.remove( importing ); - dependencyManagementImporter.importManagement( model, importMgmts, request, problems ); + return dependencyManagementImporter.importManagement( model, importMgmts, request, problems ); } private DependencyManagement loadDependencyManagement( Model model, ModelBuildingRequest request, @@ -1635,9 +1689,10 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild if ( importModel == null ) { final ModelSource importSource; + final AtomicReference modified = new AtomicReference<>(); try { - importSource = modelResolver.resolveModel( dependency ); + importSource = modelResolver.resolveModel( dependency, modified ); } catch ( UnresolvableModelException e ) { @@ -1655,6 +1710,11 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild return null; } + if ( modified.get() != null ) + { + throw new UnsupportedOperationException( "NEED TO UPDATE DEPENDENCY" ); + } + final ModelBuildingResult importResult; try { @@ -1685,7 +1745,7 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild if ( importMgmt == null ) { - importMgmt = new DependencyManagement(); + importMgmt = DependencyManagement.newInstance(); } return importMgmt; } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java index 8c7b603ab42c..02764d052d80 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java @@ -21,7 +21,7 @@ import java.util.Arrays; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.composition.DefaultDependencyManagementImporter; import org.apache.maven.model.composition.DependencyManagementImporter; import org.apache.maven.model.inheritance.DefaultInheritanceAssembler; @@ -381,8 +381,11 @@ private static class StubLifecycleBindingsInjector { @Override - public void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model injectLifecycleBindings( Model model, + ModelBuildingRequest request, + ModelProblemCollector problems ) { + return model; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java index 01d23ef3b669..3d21c238486f 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Holds data relevant for a model building event. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java index 379b5e7e1c2c..2ae68ec4adf4 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java @@ -25,8 +25,8 @@ import java.util.List; import java.util.Properties; -import org.apache.maven.model.Model; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.WorkspaceModelResolver; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java index b2fcfa05f02d..a4e9113eda50 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java @@ -25,8 +25,8 @@ import java.util.Map; import java.util.Objects; -import org.apache.maven.model.Model; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Profile; /** * Collects the output of the model builder. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java index 95c71c57190c..c2807a457dc7 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Describes a problem that was encountered during model building. A problem can either be an exception that was thrown diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java index c06869a80de9..4cd9278d60df 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java @@ -23,7 +23,7 @@ import java.util.List; import java.util.Set; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.io.ModelParseException; /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java index cc2daf8ff00b..51b81940fb61 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProcessor.java @@ -29,7 +29,7 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.io.ModelReader; import org.apache.maven.model.locator.ModelLocator; import org.eclipse.sisu.Typed; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java index 3c70b3c9af03..2e4ebe62f977 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java @@ -25,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java index 47af900a9aa6..a46bd6bcc3e9 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java @@ -22,19 +22,19 @@ import java.util.Iterator; import java.util.Map; -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.merge.ModelMerger; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.CiManagement; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.Profile; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.Reporting; +import org.apache.maven.model.v4.ModelMerger; /** * As long as Maven controls the BuildPomXMLFilter, the entities that need merging are known. @@ -47,7 +47,8 @@ class FileToRawModelMerger extends ModelMerger { @Override - protected void mergeBuild_Extensions( Build target, Build source, boolean sourceDominant, + protected void mergeBuild_Extensions( Build.Builder builder, + Build target, Build source, boolean sourceDominant, Map context ) { // don't merge @@ -55,28 +56,32 @@ protected void mergeBuild_Extensions( Build target, Build source, boolean source @Override - protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant, + protected void mergeBuildBase_Resources( BuildBase.Builder builder, + BuildBase target, BuildBase source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant, + protected void mergeBuildBase_TestResources( BuildBase.Builder builder, + BuildBase target, BuildBase source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeCiManagement_Notifiers( CiManagement target, CiManagement source, boolean sourceDominant, + protected void mergeCiManagement_Notifiers( CiManagement.Builder builder, + CiManagement target, CiManagement source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeDependencyManagement_Dependencies( DependencyManagement target, DependencyManagement source, + protected void mergeDependencyManagement_Dependencies( DependencyManagement.Builder builder, + DependencyManagement target, DependencyManagement source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); @@ -85,42 +90,48 @@ protected void mergeDependencyManagement_Dependencies( DependencyManagement targ } @Override - protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, + protected void mergeDependency_Exclusions( Dependency.Builder builder, + Dependency target, Dependency source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Contributors( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Developers( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Licenses( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant, + protected void mergeModel_MailingLists( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Profiles( Model.Builder builder, + Model target, Model source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getProfiles().iterator(); @@ -129,7 +140,8 @@ protected void mergeModel_Profiles( Model target, Model source, boolean sourceDo } @Override - protected void mergeModelBase_Dependencies( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_Dependencies( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); @@ -138,21 +150,24 @@ protected void mergeModelBase_Dependencies( ModelBase target, ModelBase source, } @Override - protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_PluginRepositories( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { - target.setPluginRepositories( source.getPluginRepositories() ); + builder.pluginRepositories( source.getPluginRepositories() ); } @Override - protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_Repositories( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergePlugin_Dependencies( Plugin target, Plugin source, boolean sourceDominant, + protected void mergePlugin_Dependencies( Plugin.Builder builder, + Plugin target, Plugin source, boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); @@ -161,28 +176,32 @@ protected void mergePlugin_Dependencies( Plugin target, Plugin source, boolean s } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, + protected void mergePlugin_Executions( Plugin.Builder builder, + Plugin target, Plugin source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, + protected void mergeReporting_Plugins( Reporting.Builder builder, + Reporting target, Reporting source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, + protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, + ReportPlugin target, ReportPlugin source, boolean sourceDominant, Map context ) { // don't merge } @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, boolean sourceDominant, Map context ) { // don't merge diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java index d12a89a420b1..c9bf1e173bb1 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java @@ -24,8 +24,8 @@ import java.util.List; import java.util.Properties; -import org.apache.maven.model.Model; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.WorkspaceModelResolver; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java index 74c1fa6c311b..414fccb30e96 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java @@ -21,7 +21,7 @@ import java.io.File; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Builds the effective model from a POM. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java index 2995b1bfb1e7..f3920e92617c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Holds data relevant for a model building event. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java index e9d18e456d34..7227c7a2fd49 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java @@ -24,7 +24,7 @@ import java.util.Collections; import java.util.List; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Signals one ore more errors during model building. The model builder tries to collect as many problems as possible diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java index 9cdb06cb1db1..157bf5cba6ba 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java @@ -24,8 +24,8 @@ import java.util.List; import java.util.Properties; -import org.apache.maven.model.Model; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.WorkspaceModelResolver; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java index 603d2140ad9b..e5fecedf4e28 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.model.Model; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Profile; /** * Collects the output of the model builder. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java index 7e0cb0daa441..fcde1c3a650a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelCacheTag.java @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; /** * Describes a tag used by the model builder to access a {@link ModelCache}. This interface basically aggregates a name @@ -85,14 +85,13 @@ public Class getType() @Override public ModelData intoCache( ModelData data ) { - Model model = ( data.getModel() != null ) ? data.getModel().clone() : null; - return new ModelData( data.getSource(), model, data.getGroupId(), data.getArtifactId(), data.getVersion() ); + return data; } @Override public ModelData fromCache( ModelData data ) { - return intoCache( data ); + return data; } }; @@ -118,13 +117,13 @@ public Class getType() @Override public DependencyManagement intoCache( DependencyManagement data ) { - return ( data != null ) ? data.clone() : null; + return data; } @Override public DependencyManagement fromCache( DependencyManagement data ) { - return intoCache( data ); + return data; } }; @@ -150,13 +149,13 @@ public Class getType() @Override public Model intoCache( Model data ) { - return ( data != null ) ? data.clone() : null; + return data; } @Override public Model fromCache( Model data ) { - return intoCache( data ); + return data; } }; } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java index 1ef4341a8e9c..ce74df2c7526 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java @@ -22,7 +22,7 @@ import java.util.Objects; import org.apache.maven.building.Source; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Holds a model along with some auxiliary information. This internal utility class assists the model builder during POM diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java index 8edab3c01d29..430e406f45b9 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java @@ -21,7 +21,7 @@ import java.util.Objects; -import org.apache.maven.model.InputLocation; +import org.apache.maven.api.model.InputLocation; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java index 150d60dcf49c..f946c17ed7d3 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java @@ -19,9 +19,9 @@ * under the License. */ -import java.io.File; +import java.nio.file.Path; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Assists in the handling of model problems. @@ -48,7 +48,7 @@ static String toSourceHint( Model model ) buffer.append( toId( model ) ); - File pomFile = model.getPomFile(); + Path pomFile = model.getPomFile(); if ( pomFile != null ) { buffer.append( " (" ).append( pomFile ).append( ')' ); @@ -63,11 +63,11 @@ static String toPath( Model model ) if ( model != null ) { - File pomFile = model.getPomFile(); + Path pomFile = model.getPomFile(); if ( pomFile != null ) { - path = pomFile.getAbsolutePath(); + path = pomFile.toAbsolutePath().toString(); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java index e041af4912db..0d3ca8b743f3 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java @@ -21,7 +21,7 @@ import java.nio.file.Path; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Context used to transform a pom file. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index b277bf3a1caf..d14c2511db01 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -27,9 +27,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -45,7 +45,7 @@ public class DefaultDependencyManagementImporter { @Override - public void importManagement( Model target, List sources, + public Model importManagement( Model target, List sources, ModelBuildingRequest request, ModelProblemCollector problems ) { if ( sources != null && !sources.isEmpty() ) @@ -63,8 +63,7 @@ public void importManagement( Model target, List } else { - depMgmt = new DependencyManagement(); - target.setDependencyManagement( depMgmt ); + depMgmt = DependencyManagement.newInstance(); } for ( DependencyManagement source : sources ) @@ -72,15 +71,14 @@ public void importManagement( Model target, List for ( Dependency dependency : source.getDependencies() ) { String key = dependency.getManagementKey(); - if ( !dependencies.containsKey( key ) ) - { - dependencies.put( key, dependency ); - } + dependencies.putIfAbsent( key, dependency ); } } - depMgmt.setDependencies( new ArrayList<>( dependencies.values() ) ); + return target.withDependencyManagement( + depMgmt.withDependencies( new ArrayList<>( dependencies.values() ) ) ); } + return target; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java index 06496429d1e4..076c19312beb 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DependencyManagementImporter.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -42,7 +42,7 @@ public interface DependencyManagementImporter * @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}. */ - void importManagement( Model target, List sources, ModelBuildingRequest request, + Model importManagement( Model target, List sources, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java index ae5ac0b7ac25..6c9812c38bf5 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java @@ -29,13 +29,13 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.Reporting; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -60,14 +60,14 @@ public class DefaultInheritanceAssembler private static final String CHILD_DIRECTORY_PROPERTY = "project.directory"; @Override - public void assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, + public Model assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, ModelProblemCollector problems ) { Map hints = new HashMap<>(); String childPath = child.getProperties().getProperty( CHILD_DIRECTORY_PROPERTY, child.getArtifactId() ); hints.put( CHILD_DIRECTORY, childPath ); hints.put( MavenModelMerger.CHILD_PATH_ADJUSTMENT, getChildPathAdjustment( child, parent, childPath ) ); - merger.merge( child, parent, false, hints ); + return merger.merge( child, parent, false, hints ); } /** @@ -106,7 +106,7 @@ private String getChildPathAdjustment( Model child, Model parent, String childDi */ if ( child.getProjectDirectory() != null ) { - childName = child.getProjectDirectory().getName(); + childName = child.getProjectDirectory().getFileName().toString(); } for ( String module : parent.getModules() ) @@ -206,7 +206,8 @@ else if ( !initialUrlEndsWithSlash ) } @Override - protected void mergeModelBase_Properties( ModelBase target, ModelBase source, boolean sourceDominant, + protected void mergeModelBase_Properties( ModelBase.Builder builder, + ModelBase target, ModelBase source, boolean sourceDominant, Map context ) { Properties merged = new Properties(); @@ -220,8 +221,8 @@ protected void mergeModelBase_Properties( ModelBase target, ModelBase source, bo putAll( merged, source.getProperties(), CHILD_DIRECTORY_PROPERTY ); merged.putAll( target.getProperties() ); } - target.setProperties( merged ); - target.setLocation( "properties", + builder.properties( merged ); + builder.location( "properties", InputLocation.merge( target.getLocation( "properties" ), source.getLocation( "properties" ), sourceDominant ) ); } @@ -238,7 +239,8 @@ private void putAll( Map s, Map t, Object exclud } @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, boolean sourceDominant, Map context ) { List src = source.getPlugins(); @@ -252,12 +254,10 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta if ( element.isInherited() || !element.getExecutions().isEmpty() ) { // NOTE: Enforce recursive merge to trigger merging/inheritance logic for executions - Plugin plugin = new Plugin(); - plugin.setLocation( "", element.getLocation( "" ) ); - plugin.setGroupId( null ); - mergePlugin( plugin, element, sourceDominant, context ); + Plugin plugin = Plugin.newInstance( false ); + plugin = mergePlugin( plugin, element, sourceDominant, context ); - Object key = getPluginKey().apply( element ); + Object key = getPluginKey().apply( plugin ); master.put( key, plugin ); } @@ -271,7 +271,7 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin existing = master.get( key ); if ( existing != null ) { - mergePlugin( element, existing, sourceDominant, context ); + element = mergePlugin( element, existing, sourceDominant, context ); master.put( key, element ); @@ -299,27 +299,31 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta } result.addAll( pending ); - target.setPlugins( result ); + builder.plugins( result ); } } @Override - protected void mergePlugin( Plugin target, Plugin source, boolean sourceDominant, Map context ) + protected Plugin mergePlugin( Plugin target, Plugin source, + boolean sourceDominant, Map context ) { + Plugin.Builder builder = Plugin.newBuilder( target ); if ( source.isInherited() ) { - mergeConfigurationContainer( target, source, sourceDominant, context ); + mergeConfigurationContainer( builder, target, source, sourceDominant, context ); } - mergePlugin_GroupId( target, source, sourceDominant, context ); - mergePlugin_ArtifactId( target, source, sourceDominant, context ); - mergePlugin_Version( target, source, sourceDominant, context ); - mergePlugin_Extensions( target, source, sourceDominant, context ); - mergePlugin_Dependencies( target, source, sourceDominant, context ); - mergePlugin_Executions( target, source, sourceDominant, context ); + mergePlugin_GroupId( builder, target, source, sourceDominant, context ); + mergePlugin_ArtifactId( builder, target, source, sourceDominant, context ); + mergePlugin_Version( builder, target, source, sourceDominant, context ); + mergePlugin_Extensions( builder, target, source, sourceDominant, context ); + mergePlugin_Executions( builder, target, source, sourceDominant, context ); + mergePlugin_Dependencies( builder, target, source, sourceDominant, context ); + return builder.build(); } @Override - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, + protected void mergeReporting_Plugins( Reporting.Builder builder, + Reporting target, Reporting source, boolean sourceDominant, Map context ) { List src = source.getPlugins(); @@ -331,16 +335,13 @@ protected void mergeReporting_Plugins( Reporting target, Reporting source, boole for ( ReportPlugin element : src ) { - Object key = getReportPluginKey().apply( element ); if ( element.isInherited() ) { // NOTE: Enforce recursive merge to trigger merging/inheritance logic for executions as well - ReportPlugin plugin = new ReportPlugin(); - plugin.setLocation( "", element.getLocation( "" ) ); - plugin.setGroupId( null ); - mergeReportPlugin( plugin, element, sourceDominant, context ); + ReportPlugin plugin = ReportPlugin.newInstance(); + plugin = mergeReportPlugin( plugin, element, sourceDominant, context ); - merged.put( key, plugin ); + merged.put( getReportPluginKey().apply( element ), plugin ); } } @@ -350,12 +351,12 @@ protected void mergeReporting_Plugins( Reporting target, Reporting source, boole ReportPlugin existing = merged.get( key ); if ( existing != null ) { - mergeReportPlugin( element, existing, sourceDominant, context ); + element = mergeReportPlugin( element, existing, sourceDominant, context ); } merged.put( key, element ); } - target.setPlugins( new ArrayList<>( merged.values() ) ); + builder.plugins( new ArrayList<>( merged.values() ) ); } } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java index a191e52dd1d6..0badb7a58bb0 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/InheritanceAssembler.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -42,7 +42,7 @@ public interface InheritanceAssembler * @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}. */ - void assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, + Model assembleModelInheritance( Model child, Model parent, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java index 50a78be76104..d25513edff7b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java @@ -29,7 +29,7 @@ import javax.inject.Inject; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.path.PathTranslator; 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 5fc4c9c6791e..dbb9780c7da1 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 @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java deleted file mode 100644 index 99f55bd70cca..000000000000 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringSearchModelInterpolator.java +++ /dev/null @@ -1,527 +0,0 @@ -package org.apache.maven.model.interpolation; - -/* - * 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. - */ - -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.Model; -import org.apache.maven.model.building.ModelBuildingRequest; -import org.apache.maven.model.building.ModelProblem.Severity; -import org.apache.maven.model.building.ModelProblem.Version; -import org.apache.maven.model.building.ModelProblemCollector; -import org.apache.maven.model.building.ModelProblemCollectorRequest; -import org.apache.maven.model.path.PathTranslator; -import org.apache.maven.model.path.UrlNormalizer; -import org.codehaus.plexus.interpolation.InterpolationException; -import org.codehaus.plexus.interpolation.InterpolationPostProcessor; -import org.codehaus.plexus.interpolation.RecursionInterceptor; -import org.codehaus.plexus.interpolation.StringSearchInterpolator; -import org.codehaus.plexus.interpolation.ValueSource; - -import java.io.File; -import java.lang.reflect.Array; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.LinkedList; -import java.util.List; -import java.util.Map; -import java.util.concurrent.ConcurrentHashMap; - -import javax.inject.Inject; - -/** - * StringSearchModelInterpolator - * @deprecated replaced by StringVisitorModelInterpolator (MNG-6697) - */ -@Deprecated -public class StringSearchModelInterpolator - extends AbstractStringBasedModelInterpolator -{ - private static final Map, InterpolateObjectAction.CacheItem> CACHED_ENTRIES = - new ConcurrentHashMap<>( 80, 0.75f, 2 ); - // Empirical data from 3.x, actual =40 - - private interface InnerInterpolator - { - String interpolate( String value ); - } - - @Inject - public StringSearchModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer, - ModelVersionProcessor processor ) - { - super( pathTranslator, urlNormalizer, processor ); - } - - @Override - public Model interpolateModel( Model model, File projectDir, ModelBuildingRequest config, - ModelProblemCollector problems ) - { - interpolateObject( model, model, projectDir, config, problems ); - return model; - } - - void interpolateObject( Object obj, Model model, File projectDir, ModelBuildingRequest config, - ModelProblemCollector problems ) - { - List valueSources = createValueSources( model, projectDir, config, problems ); - List postProcessors = createPostProcessors( model, projectDir, config ); - - InnerInterpolator innerInterpolator = createInterpolator( valueSources, postProcessors, problems ); - - PrivilegedAction action = new InterpolateObjectAction( obj, innerInterpolator, problems ); - AccessController.doPrivileged( action ); - } - - private InnerInterpolator createInterpolator( List valueSources, - List postProcessors, - final ModelProblemCollector problems ) - { - final Map cache = new HashMap<>(); - final StringSearchInterpolator interpolator = new StringSearchInterpolator(); - interpolator.setCacheAnswers( true ); - for ( ValueSource vs : valueSources ) - { - interpolator.addValueSource( vs ); - } - for ( InterpolationPostProcessor postProcessor : postProcessors ) - { - interpolator.addPostProcessor( postProcessor ); - } - final RecursionInterceptor recursionInterceptor = createRecursionInterceptor(); - return value -> - { - if ( value != null && value.contains( "${" ) ) - { - String c = cache.get( value ); - if ( c == null ) - { - try - { - c = interpolator.interpolate( value, recursionInterceptor ); - } - catch ( InterpolationException e ) - { - problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ) - .setMessage( e.getMessage() ).setException( e ) ); - } - cache.put( value, c ); - } - return c; - } - return value; - }; - } - - private static final class InterpolateObjectAction - implements PrivilegedAction - { - private final LinkedList interpolationTargets; - - private final InnerInterpolator interpolator; - - private final ModelProblemCollector problems; - - InterpolateObjectAction( Object target, InnerInterpolator interpolator, ModelProblemCollector problems ) - { - this.interpolationTargets = new LinkedList<>(); - interpolationTargets.add( target ); - this.interpolator = interpolator; - this.problems = problems; - } - - @Override - public Object run() - { - while ( !interpolationTargets.isEmpty() ) - { - Object obj = interpolationTargets.removeFirst(); - - traverseObjectWithParents( obj.getClass(), obj ); - } - return null; - } - - private String interpolate( String value ) - { - return interpolator.interpolate( value ); - } - - private void traverseObjectWithParents( Class cls, Object target ) - { - if ( cls == null ) - { - return; - } - - CacheItem cacheEntry = getCacheEntry( cls ); - if ( cacheEntry.isArray() ) - { - evaluateArray( target, this ); - } - else if ( cacheEntry.isQualifiedForInterpolation ) - { - cacheEntry.interpolate( target, this ); - - traverseObjectWithParents( cls.getSuperclass(), target ); - } - } - - private CacheItem getCacheEntry( Class cls ) - { - CacheItem cacheItem = CACHED_ENTRIES.get( cls ); - if ( cacheItem == null ) - { - cacheItem = new CacheItem( cls ); - CACHED_ENTRIES.put( cls, cacheItem ); - } - return cacheItem; - } - - private static void evaluateArray( Object target, InterpolateObjectAction ctx ) - { - int len = Array.getLength( target ); - for ( int i = 0; i < len; i++ ) - { - Object value = Array.get( target, i ); - if ( value != null ) - { - if ( String.class == value.getClass() ) - { - String interpolated = ctx.interpolate( (String) value ); - - if ( !interpolated.equals( value ) ) - { - Array.set( target, i, interpolated ); - } - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - - private static class CacheItem - { - private final boolean isArray; - - private final boolean isQualifiedForInterpolation; - - private final CacheField[] fields; - - private boolean isQualifiedForInterpolation( Class cls ) - { - Package pkg = cls.getPackage(); - if ( pkg == null ) - { - return true; - } - String pkgName = pkg.getName(); - return !pkgName.startsWith( "java." ) && !pkgName.startsWith( "javax." ); - } - - private boolean isQualifiedForInterpolation( Field field, Class fieldType ) - { - if ( Map.class.equals( fieldType ) && "locations".equals( field.getName() ) ) - { - return false; - } - if ( InputLocation.class.equals( fieldType ) ) - { - return false; - } - - //noinspection SimplifiableIfStatement - if ( fieldType.isPrimitive() ) - { - return false; - } - - return !"parent".equals( field.getName() ); - } - - CacheItem( Class clazz ) - { - this.isQualifiedForInterpolation = isQualifiedForInterpolation( clazz ); - this.isArray = clazz.isArray(); - List fields = new ArrayList<>(); - if ( isQualifiedForInterpolation ) - { - for ( Field currentField : clazz.getDeclaredFields() ) - { - Class type = currentField.getType(); - if ( isQualifiedForInterpolation( currentField, type ) ) - { - if ( String.class == type ) - { - if ( !Modifier.isFinal( currentField.getModifiers() ) ) - { - fields.add( new StringField( currentField ) ); - } - } - else if ( List.class.isAssignableFrom( type ) ) - { - fields.add( new ListField( currentField ) ); - } - else if ( Collection.class.isAssignableFrom( type ) ) - { - throw new RuntimeException( - "We dont interpolate into collections, use a list instead" ); - } - else if ( Map.class.isAssignableFrom( type ) ) - { - fields.add( new MapField( currentField ) ); - } - else - { - fields.add( new ObjectField( currentField ) ); - } - } - } - } - this.fields = fields.toArray( new CacheField[0] ); - } - - void interpolate( Object target, InterpolateObjectAction interpolateObjectAction ) - { - for ( CacheField field : fields ) - { - field.interpolate( target, interpolateObjectAction ); - } - } - - boolean isArray() - { - return isArray; - } - } - - abstract static class CacheField - { - final Field field; - - CacheField( Field field ) - { - this.field = field; - field.setAccessible( true ); - } - - void interpolate( Object target, InterpolateObjectAction interpolateObjectAction ) - { - try - { - doInterpolate( target, interpolateObjectAction ); - } - catch ( IllegalArgumentException e ) - { - interpolateObjectAction.problems.add( - new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage( - "Failed to interpolate field3: " + field + " on class: " - + field.getType().getName() ).setException( - e ) ); // TODO Not entirely the same message - } - catch ( IllegalAccessException e ) - { - interpolateObjectAction.problems.add( - new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ).setMessage( - "Failed to interpolate field4: " + field + " on class: " - + field.getType().getName() ).setException( e ) ); - } - } - - abstract void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException; - } - - static final class StringField - extends CacheField - { - StringField( Field field ) - { - super( field ); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - String value = (String) field.get( target ); - if ( value == null ) - { - return; - } - - String interpolated = ctx.interpolate( value ); - - if ( interpolated != null && !interpolated.equals( value ) ) - { - field.set( target, interpolated ); - } - } - } - - static final class ListField - extends CacheField - { - ListField( Field field ) - { - super( field ); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - @SuppressWarnings( "unchecked" ) List c = (List) field.get( target ); - if ( c == null ) - { - return; - } - - for ( int i = 0, size = c.size(); i < size; i++ ) - { - Object value = c.get( i ); - - if ( value != null ) - { - if ( String.class == value.getClass() ) - { - String interpolated = ctx.interpolate( (String) value ); - - if ( !interpolated.equals( value ) ) - { - try - { - c.set( i, interpolated ); - } - catch ( UnsupportedOperationException e ) - { - return; - } - } - } - else - { - if ( value.getClass().isArray() ) - { - evaluateArray( value, ctx ); - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - } - } - - static final class MapField - extends CacheField - { - MapField( Field field ) - { - super( field ); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - @SuppressWarnings( "unchecked" ) Map m = (Map) field.get( target ); - if ( m == null || m.isEmpty() ) - { - return; - } - - for ( Map.Entry entry : m.entrySet() ) - { - Object value = entry.getValue(); - - if ( value == null ) - { - continue; - } - - if ( String.class == value.getClass() ) - { - String interpolated = ctx.interpolate( (String) value ); - - if ( interpolated != null && !interpolated.equals( value ) ) - { - try - { - entry.setValue( interpolated ); - } - catch ( UnsupportedOperationException ignore ) - { - // nop - } - } - } - else if ( value.getClass().isArray() ) - { - evaluateArray( value, ctx ); - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - - static final class ObjectField - extends CacheField - { - private final boolean isArray; - - ObjectField( Field field ) - { - super( field ); - this.isArray = field.getType().isArray(); - } - - @Override - void doInterpolate( Object target, InterpolateObjectAction ctx ) - throws IllegalAccessException - { - Object value = field.get( target ); - if ( value != null ) - { - if ( isArray ) - { - evaluateArray( value, ctx ); - } - else - { - ctx.interpolationTargets.add( value ); - } - } - } - } - } -} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java index e2438d540a7a..5bba995fd1b7 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java @@ -22,56 +22,19 @@ import java.io.File; import java.util.HashMap; import java.util.List; -import java.util.ListIterator; import java.util.Map; -import java.util.Properties; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.ActivationOS; -import org.apache.maven.model.ActivationProperty; -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.Contributor; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Developer; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Extension; -import org.apache.maven.model.IssueManagement; -import org.apache.maven.model.License; -import org.apache.maven.model.MailingList; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Notifier; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; -import org.apache.maven.model.Relocation; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Repository; -import org.apache.maven.model.RepositoryBase; -import org.apache.maven.model.RepositoryPolicy; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblemCollectorRequest; +import org.apache.maven.model.v4.ModelTransformer; import org.apache.maven.model.path.PathTranslator; import org.apache.maven.model.path.UrlNormalizer; import org.codehaus.plexus.interpolation.InterpolationException; @@ -79,7 +42,6 @@ import org.codehaus.plexus.interpolation.RecursionInterceptor; import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.codehaus.plexus.interpolation.ValueSource; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * StringVisitorModelInterpolator @@ -92,7 +54,8 @@ public class StringVisitorModelInterpolator extends AbstractStringBasedModelInterpolator { @Inject - public StringVisitorModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer, + public StringVisitorModelInterpolator( PathTranslator pathTranslator, + UrlNormalizer urlNormalizer, ModelVersionProcessor processor ) { super( pathTranslator, urlNormalizer, processor ); @@ -113,9 +76,7 @@ public Model interpolateModel( Model model, File projectDir, ModelBuildingReques InnerInterpolator innerInterpolator = createInterpolator( valueSources, postProcessors, problems ); - new ModelVisitor( innerInterpolator ).visit( model ); - - return model; + return new ModelTransformer( innerInterpolator::interpolate ).visit( model ); } private InnerInterpolator createInterpolator( List valueSources, @@ -158,1307 +119,4 @@ private InnerInterpolator createInterpolator( List valueS }; } - @SuppressWarnings( "StringEquality" ) - private static final class ModelVisitor - { - private final InnerInterpolator interpolator; - - ModelVisitor( InnerInterpolator interpolator ) - { - this.interpolator = interpolator; - } - - void visit( Model model ) - { - if ( model != null ) - { - visit( (ModelBase) model ); - // ModelVersion - String orgModelVersion = model.getModelVersion(); - String intModelVersion = interpolate( orgModelVersion ); - if ( orgModelVersion != intModelVersion ) - { - model.setModelVersion( intModelVersion ); - } - visit( model.getParent() ); - // GroupId - String orgGroupId = model.getGroupId(); - String intGroupId = interpolate( orgGroupId ); - if ( orgGroupId != intGroupId ) - { - model.setGroupId( intGroupId ); - } - // ArtifactId - String orgArtifactId = model.getArtifactId(); - String intArtifactId = interpolate( orgArtifactId ); - if ( orgArtifactId != intArtifactId ) - { - model.setArtifactId( intArtifactId ); - } - // Version - String orgVersion = model.getVersion(); - String intVersion = interpolate( orgVersion ); - if ( orgVersion != intVersion ) - { - model.setVersion( intVersion ); - } - - // Packaging - String orgPackaging = model.getPackaging(); - String intPackaging = interpolate( orgPackaging ); - if ( orgPackaging != intPackaging ) - { - model.setPackaging( intPackaging ); - } - // Name - String orgName = model.getName(); - String intName = interpolate( orgName ); - if ( orgName != intName ) - { - model.setName( intName ); - } - // Description - String orgDescription = model.getDescription(); - String intDescription = interpolate( orgDescription ); - if ( orgDescription != intDescription ) - { - model.setDescription( intDescription ); - } - // Url - String orgUrl = model.getUrl(); - String intUrl = interpolate( orgUrl ); - if ( orgUrl != intUrl ) - { - model.setUrl( intUrl ); - } - // ChildProjectUrlInheritAppendPath - String orgChildProjectUrlInheritAppendPath = model.getChildProjectUrlInheritAppendPath(); - String intChildProjectUrlInheritAppendPath = interpolate( orgChildProjectUrlInheritAppendPath ); - if ( orgChildProjectUrlInheritAppendPath != intChildProjectUrlInheritAppendPath ) - { - model.setChildProjectUrlInheritAppendPath( intChildProjectUrlInheritAppendPath ); - } - // InceptionYear - String orgInceptionYear = model.getInceptionYear(); - String intInceptionYear = interpolate( orgInceptionYear ); - if ( orgInceptionYear != intInceptionYear ) - { - model.setInceptionYear( intInceptionYear ); - } - visit( model.getOrganization() ); - for ( License license : model.getLicenses() ) - { - visit( license ); - } - for ( Developer developer : model.getDevelopers() ) - { - visit( developer ); - } - for ( Contributor contributor : model.getContributors() ) - { - visit( contributor ); - } - for ( MailingList mailingList : model.getMailingLists() ) - { - visit( mailingList ); - } - visit( model.getPrerequisites() ); - visit( model.getScm() ); - visit( model.getIssueManagement() ); - visit( model.getCiManagement() ); - visit( model.getBuild() ); - for ( Profile profile : model.getProfiles() ) - { - visit( profile ); - } - - } - } - - private void visit( Parent parent ) - { - if ( parent != null ) - { - String org, val; - // GroupId - org = parent.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - parent.setGroupId( val ); - } - // ArtifactId - org = parent.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - parent.setArtifactId( val ); - } - // Version - org = parent.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - parent.setVersion( val ); - } - // RelativePath - org = parent.getRelativePath(); - val = interpolate( org ); - if ( org != val ) - { - parent.setRelativePath( val ); - } - } - } - - private void visit( Organization organization ) - { - if ( organization != null ) - { - String org, val; - // Name - org = organization.getName(); - val = interpolate( org ); - if ( org != val ) - { - organization.setName( val ); - } - // Url - org = organization.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - organization.setUrl( val ); - } - } - } - - private void visit( License license ) - { - if ( license != null ) - { - String org, val; - // Name - org = license.getName(); - val = interpolate( org ); - if ( org != val ) - { - license.setName( val ); - } - // Url - org = license.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - license.setUrl( val ); - } - // Distribution - org = license.getDistribution(); - val = interpolate( org ); - if ( org != val ) - { - license.setDistribution( val ); - } - // Comments - org = license.getComments(); - val = interpolate( org ); - if ( org != val ) - { - license.setComments( val ); - } - } - } - - private void visit( Developer developer ) - { - if ( developer != null ) - { - String org, val; - // Contributor - visit( (Contributor) developer ); - // Distribution - org = developer.getId(); - val = interpolate( org ); - if ( org != val ) - { - developer.setId( val ); - } - } - } - - private void visit( Contributor contributor ) - { - if ( contributor != null ) - { - String org, val; - // Name - org = contributor.getName(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setName( val ); - } - // Email - org = contributor.getEmail(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setEmail( val ); - } - // Url - org = contributor.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setUrl( val ); - } - // Organization - org = contributor.getOrganization(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setOrganization( val ); - } - // OrganizationUrl - org = contributor.getOrganizationUrl(); - val = interpolate( org ); - if ( org != val ) - { - contributor.setOrganizationUrl( val ); - } - // Roles - visit( contributor.getRoles() ); - } - } - - private void visit( MailingList mailingList ) - { - if ( mailingList != null ) - { - String org, val; - // Name - org = mailingList.getName(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setName( val ); - } - // Subscribe - org = mailingList.getSubscribe(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setSubscribe( val ); - } - // Unsubscribe - org = mailingList.getUnsubscribe(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setUnsubscribe( val ); - } - // Post - org = mailingList.getPost(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setPost( val ); - } - // Archive - org = mailingList.getArchive(); - val = interpolate( org ); - if ( org != val ) - { - mailingList.setArchive( val ); - } - } - } - - private void visit( Prerequisites prerequisites ) - { - if ( prerequisites != null ) - { - String org, val; - // Maven - org = prerequisites.getMaven(); - val = interpolate( org ); - if ( org != val ) - { - prerequisites.setMaven( val ); - } - } - } - - private void visit( Scm scm ) - { - if ( scm != null ) - { - String org, val; - // Connection - org = scm.getConnection(); - val = interpolate( org ); - if ( org != val ) - { - scm.setConnection( val ); - } - // DeveloperConnection - org = scm.getDeveloperConnection(); - val = interpolate( org ); - if ( org != val ) - { - scm.setDeveloperConnection( val ); - } - // Tag - org = scm.getTag(); - val = interpolate( org ); - if ( org != val ) - { - scm.setTag( val ); - } - // Url - org = scm.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - scm.setUrl( val ); - } - // ChildScmConnectionInheritAppendPath - org = scm.getChildScmConnectionInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - scm.setChildScmConnectionInheritAppendPath( val ); - } - // ChildScmDeveloperConnectionInheritAppendPath - org = scm.getChildScmDeveloperConnectionInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - scm.setChildScmDeveloperConnectionInheritAppendPath( val ); - } - // ChildScmUrlInheritAppendPath - org = scm.getChildScmUrlInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - scm.setChildScmUrlInheritAppendPath( val ); - } - } - } - - private void visit( IssueManagement issueManagement ) - { - if ( issueManagement != null ) - { - String org, val; - // System - org = issueManagement.getSystem(); - val = interpolate( org ); - if ( org != val ) - { - issueManagement.setSystem( val ); - } - // Url - org = issueManagement.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - issueManagement.setUrl( val ); - } - } - } - - private void visit( CiManagement ciManagement ) - { - if ( ciManagement != null ) - { - String org, val; - // System - org = ciManagement.getSystem(); - val = interpolate( org ); - if ( org != val ) - { - ciManagement.setSystem( val ); - } - // Url - org = ciManagement.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - ciManagement.setUrl( val ); - } - // Notifiers - for ( Notifier notifier : ciManagement.getNotifiers() ) - { - visit( notifier ); - } - } - } - - private void visit( Notifier notifier ) - { - if ( notifier != null ) - { - String org, val; - // Type - org = notifier.getType(); - val = interpolate( org ); - if ( org != val ) - { - notifier.setType( val ); - } - // Configuration - visit( notifier.getConfiguration() ); - } - } - - private void visit( BuildBase build ) - { - if ( build != null ) - { - String org, val; - // Plugins - for ( Plugin plugin : build.getPlugins() ) - { - visit( plugin ); - } - // PluginManagement - visit( build.getPluginManagement() ); - // DefaultGoal - org = build.getDefaultGoal(); - val = interpolate( org ); - if ( org != val ) - { - build.setDefaultGoal( val ); - } - // Resources - for ( Resource resource : build.getResources() ) - { - visit( resource ); - } - // TestResources - for ( Resource resource : build.getTestResources() ) - { - visit( resource ); - } - // Directory - org = build.getDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setDirectory( val ); - } - // FinalName - org = build.getFinalName(); - val = interpolate( org ); - if ( org != val ) - { - build.setFinalName( val ); - } - // Filters - visit( build.getFilters() ); - } - } - - private void visit( PluginManagement pluginManagement ) - { - if ( pluginManagement != null ) - { - for ( Plugin plugin : pluginManagement.getPlugins() ) - { - visit( plugin ); - } - } - } - - private void visit( Build build ) - { - if ( build != null ) - { - String org, val; - // BuildBase - visit( (BuildBase) build ); - // SourceDirectory - org = build.getSourceDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setSourceDirectory( val ); - } - // ScriptSourceDirectory - org = build.getScriptSourceDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setScriptSourceDirectory( val ); - } - // TestSourceDirectory - org = build.getTestSourceDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setTestSourceDirectory( val ); - } - // OutputDirectory - org = build.getOutputDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setOutputDirectory( val ); - } - // TestOutputDirectory - org = build.getTestOutputDirectory(); - val = interpolate( org ); - if ( org != val ) - { - build.setTestOutputDirectory( val ); - } - // Extensions - for ( Extension extension : build.getExtensions() ) - { - visit( extension ); - } - } - } - - private void visit( Resource resource ) - { - if ( resource != null ) - { - String org, val; - // Includes - visit( resource.getIncludes() ); - // Excludes - visit( resource.getExcludes() ); - // Directory - org = resource.getDirectory(); - val = interpolate( org ); - if ( org != val ) - { - resource.setDirectory( val ); - } - // TargetPath - org = resource.getTargetPath(); - val = interpolate( org ); - if ( org != val ) - { - resource.setTargetPath( val ); - } - // Filtering - org = resource.getFiltering(); - val = interpolate( org ); - if ( org != val ) - { - resource.setFiltering( val ); - } - } - } - - private void visit( Plugin plugin ) - { - if ( plugin != null ) - { - String org, val; - // Inherited - org = plugin.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) plugin.getConfiguration() ); - // GroupId - org = plugin.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setGroupId( val ); - } - // ArtifactId - org = plugin.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setArtifactId( val ); - } - // Version - org = plugin.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setVersion( val ); - } - // Extensions - org = plugin.getExtensions(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setExtensions( val ); - } - // Executions - for ( PluginExecution execution : plugin.getExecutions() ) - { - visit( execution ); - } - // Dependencies - for ( Dependency dependency : plugin.getDependencies() ) - { - visit( dependency ); - } - } - } - - private void visit( PluginExecution execution ) - { - if ( execution != null ) - { - String org, val; - // Inherited - org = execution.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - execution.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) execution.getConfiguration() ); - // Id - org = execution.getId(); - val = interpolate( org ); - if ( org != val ) - { - execution.setId( val ); - } - // Phase - org = execution.getPhase(); - val = interpolate( org ); - if ( org != val ) - { - execution.setPhase( val ); - } - // Goals - visit( execution.getGoals() ); - } - } - - private void visit( Xpp3Dom dom ) - { - if ( dom != null ) - { - String org, val; - // Content - org = dom.getValue(); - val = interpolate( org ); - if ( org != val ) - { - dom.setValue( val ); - } - // Attributes - for ( String attr : dom.getAttributeNames() ) - { - org = dom.getAttribute( attr ); - val = interpolate( org ); - if ( org != val ) - { - dom.setAttribute( attr, val ); - } - } - // Children - for ( int i = 0, l = dom.getChildCount(); i < l; i++ ) - { - visit( dom.getChild( i ) ); - } - } - } - - private void visit( Extension extension ) - { - if ( extension != null ) - { - String org, val; - // GroupId - org = extension.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - extension.setGroupId( val ); - } - // ArtifactId - org = extension.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - extension.setArtifactId( val ); - } - // Version - org = extension.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - extension.setVersion( val ); - } - } - } - - private void visit( Profile profile ) - { - if ( profile != null ) - { - String org, val; - // ModelBase - visit( (ModelBase) profile ); - // Id - org = profile.getId(); - val = interpolate( org ); - if ( org != val ) - { - profile.setId( val ); - } - // Activation - visit( profile.getActivation() ); - // Build - visit( profile.getBuild() ); - } - } - - private void visit( Activation activation ) - { - if ( activation != null ) - { - String org, val; - // Jdk - org = activation.getJdk(); - val = interpolate( org ); - if ( org != val ) - { - activation.setJdk( val ); - } - // OS - visit( activation.getOs() ); - // Property - visit( activation.getProperty() ); - // File - visit( activation.getFile() ); - } - } - - private void visit( ActivationOS activationOS ) - { - if ( activationOS != null ) - { - String org, val; - // Name - org = activationOS.getName(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setName( val ); - } - // Family - org = activationOS.getFamily(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setFamily( val ); - } - // Arch - org = activationOS.getArch(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setArch( val ); - } - // Version - org = activationOS.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - activationOS.setVersion( val ); - } - } - } - - private void visit( ActivationProperty activationProperty ) - { - if ( activationProperty != null ) - { - String org, val; - // Name - org = activationProperty.getName(); - val = interpolate( org ); - if ( org != val ) - { - activationProperty.setName( val ); - } - // Value - org = activationProperty.getValue(); - val = interpolate( org ); - if ( org != val ) - { - activationProperty.setValue( val ); - } - } - } - - private void visit( ActivationFile activationFile ) - { - if ( activationFile != null ) - { - String org, val; - // Missing - org = activationFile.getMissing(); - val = interpolate( org ); - if ( org != val ) - { - activationFile.setMissing( val ); - } - // Exists - org = activationFile.getExists(); - val = interpolate( org ); - if ( org != val ) - { - activationFile.setExists( val ); - } - } - } - - private void visit( ModelBase modelBase ) - { - if ( modelBase != null ) - { - visit( modelBase.getModules() ); - visit( modelBase.getDistributionManagement() ); - visit( modelBase.getProperties() ); - visit( modelBase.getDependencyManagement() ); - for ( Dependency dependency : modelBase.getDependencies() ) - { - visit( dependency ); - } - for ( Repository repository : modelBase.getRepositories() ) - { - visit( repository ); - } - for ( Repository repository : modelBase.getPluginRepositories() ) - { - visit( repository ); - } - visit( modelBase.getReporting() ); - } - } - - private void visit( DistributionManagement distributionManagement ) - { - if ( distributionManagement != null ) - { - String org, val; - // Repository - visit( distributionManagement.getRepository() ); - // SnapshotRepository - visit( distributionManagement.getSnapshotRepository() ); - // Site - visit( distributionManagement.getSite() ); - // DownloadUrl - org = distributionManagement.getDownloadUrl(); - val = interpolate( org ); - if ( org != val ) - { - distributionManagement.setDownloadUrl( val ); - } - // Relocation - visit( distributionManagement.getRelocation() ); - } - } - - private void visit( Site site ) - { - if ( site != null ) - { - String org, val; - // Id - org = site.getId(); - val = interpolate( org ); - if ( org != val ) - { - site.setId( val ); - } - // Name - org = site.getName(); - val = interpolate( org ); - if ( org != val ) - { - site.setName( val ); - } - // Url - org = site.getUrl(); - val = interpolate( org ); - if ( org != val ) - { - site.setUrl( val ); - } - // ChildSiteUrlInheritAppendPath - org = site.getChildSiteUrlInheritAppendPath(); - val = interpolate( org ); - if ( org != val ) - { - site.setChildSiteUrlInheritAppendPath( val ); - } - } - } - - private void visit( Relocation relocation ) - { - if ( relocation != null ) - { - String org, val; - // GroupId - org = relocation.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setGroupId( val ); - } - // ArtifactId - org = relocation.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setArtifactId( val ); - } - // Version - org = relocation.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setVersion( val ); - } - // Message - org = relocation.getMessage(); - val = interpolate( org ); - if ( org != val ) - { - relocation.setMessage( val ); - } - } - } - - private void visit( DependencyManagement dependencyManagement ) - { - if ( dependencyManagement != null ) - { - // Dependencies - for ( Dependency dependency : dependencyManagement.getDependencies() ) - { - visit( dependency ); - } - } - } - - private void visit( Repository repository ) - { - if ( repository != null ) - { - visit( (RepositoryBase) repository ); - visit( repository.getReleases() ); - visit( repository.getSnapshots() ); - } - } - - private void visit( RepositoryBase repositoryBase ) - { - if ( repositoryBase != null ) - { - // Id - String orgId = repositoryBase.getId(); - String intId = interpolate( orgId ); - if ( orgId != intId ) - { - repositoryBase.setId( intId ); - } - // Name - String orgName = repositoryBase.getName(); - String intName = interpolate( orgName ); - if ( orgName != intName ) - { - repositoryBase.setName( intName ); - } - // Url - String orgUrl = repositoryBase.getUrl(); - String intUrl = interpolate( orgUrl ); - if ( orgUrl != intUrl ) - { - repositoryBase.setUrl( intUrl ); - } - // Layout - String orgLayout = repositoryBase.getLayout(); - String intLayout = interpolate( orgLayout ); - if ( orgLayout != intLayout ) - { - repositoryBase.setLayout( intLayout ); - } - } - } - - private void visit( RepositoryPolicy repositoryPolicy ) - { - if ( repositoryPolicy != null ) - { - // Enabled - String orgEnabled = repositoryPolicy.getEnabled(); - String intEnabled = interpolate( orgEnabled ); - if ( orgEnabled != intEnabled ) - { - repositoryPolicy.setEnabled( intEnabled ); - } - // UpdatePolicy - String orgUpdatePolicy = repositoryPolicy.getUpdatePolicy(); - String intUpdatePolicy = interpolate( orgUpdatePolicy ); - if ( orgUpdatePolicy != intUpdatePolicy ) - { - repositoryPolicy.setUpdatePolicy( intUpdatePolicy ); - } - // ChecksumPolicy - String orgChecksumPolicy = repositoryPolicy.getChecksumPolicy(); - String intChecksumPolicy = interpolate( orgChecksumPolicy ); - if ( orgChecksumPolicy != intChecksumPolicy ) - { - repositoryPolicy.setChecksumPolicy( intChecksumPolicy ); - } - } - } - - private void visit( Dependency dependency ) - { - if ( dependency != null ) - { - String org, val; - // GroupId - org = dependency.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setGroupId( val ); - dependency.clearManagementKey(); - } - // ArtifactId - org = dependency.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setArtifactId( val ); - dependency.clearManagementKey(); - } - // Version - org = dependency.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setVersion( val ); - } - // Type - org = dependency.getType(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setType( val ); - dependency.clearManagementKey(); - } - // Classifier - org = dependency.getClassifier(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setClassifier( val ); - dependency.clearManagementKey(); - } - // Scope - org = dependency.getScope(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setScope( val ); - } - // SystemPath - org = dependency.getSystemPath(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setSystemPath( val ); - } - // Exclusions - for ( Exclusion exclusion : dependency.getExclusions() ) - { - visit( exclusion ); - } - // Optional - org = dependency.getOptional(); - val = interpolate( org ); - if ( org != val ) - { - dependency.setOptional( val ); - } - } - } - - private void visit( Exclusion exclusion ) - { - if ( exclusion != null ) - { - String org, val; - // GroupId - org = exclusion.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - exclusion.setGroupId( val ); - } - // ArtifactId - org = exclusion.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - exclusion.setArtifactId( val ); - } - } - } - - private void visit( Reporting reporting ) - { - if ( reporting != null ) - { - String org, val; - // ExcludeDefaults - org = reporting.getExcludeDefaults(); - val = interpolate( org ); - if ( org != val ) - { - reporting.setExcludeDefaults( val ); - } - // OutputDirectory - org = reporting.getOutputDirectory(); - val = interpolate( org ); - if ( org != val ) - { - reporting.setOutputDirectory( val ); - } - // Plugins - for ( ReportPlugin plugin : reporting.getPlugins() ) - { - visit( plugin ); - } - } - } - - private void visit( ReportPlugin plugin ) - { - if ( plugin != null ) - { - String org, val; - // Inherited - org = plugin.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) plugin.getConfiguration() ); - // GroupId - org = plugin.getGroupId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setGroupId( val ); - } - // ArtifactId - org = plugin.getArtifactId(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setArtifactId( val ); - } - // Version - org = plugin.getVersion(); - val = interpolate( org ); - if ( org != val ) - { - plugin.setVersion( val ); - } - // ReportSets - for ( ReportSet reportSet : plugin.getReportSets() ) - { - visit( reportSet ); - } - } - } - - private void visit( ReportSet reportSet ) - { - if ( reportSet != null ) - { - String org, val; - // Inherited - org = reportSet.getInherited(); - val = interpolate( org ); - if ( org != val ) - { - reportSet.setInherited( val ); - } - // Configuration - visit( (Xpp3Dom) reportSet.getConfiguration() ); - // Id - org = reportSet.getId(); - val = interpolate( org ); - if ( org != val ) - { - reportSet.setId( val ); - } - // Reports - visit( reportSet.getReports() ); - } - } - - private void visit( Properties properties ) - { - if ( properties != null ) - { - for ( Map.Entry entry : properties.entrySet() ) - { - Object v = entry.getValue(); - if ( v instanceof String ) - { - String value = (String) v; - String inter = interpolate( value ); - if ( value != inter && inter != null ) - { - entry.setValue( inter ); - } - } - } - } - } - - private void visit( List list ) - { - if ( list != null ) - { - ListIterator it = list.listIterator(); - while ( it.hasNext() ) - { - String value = it.next(); - String inter = interpolate( value ); - if ( value != inter ) - { - it.set( inter ); - } - } - } - } - - private String interpolate( String value ) - { - return interpolator.interpolate( value ); - } - - } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java index 3501df9760e6..57edccf3bb63 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java @@ -23,8 +23,6 @@ import java.io.IOException; import java.io.InputStream; import java.io.Reader; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; import java.nio.file.Path; import java.util.Map; import java.util.Objects; @@ -33,12 +31,12 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelSourceTransformer; import org.apache.maven.model.building.TransformerContext; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.apache.maven.model.io.xpp3.MavenXpp3ReaderEx; +import org.apache.maven.model.v4.MavenXpp3Reader; +import org.apache.maven.model.v4.MavenXpp3ReaderEx; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.XmlStreamReader; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; @@ -58,10 +56,6 @@ public class DefaultModelReader { private final ModelSourceTransformer transformer; - private Method readMethod; - - private Method readMethodEx; - @Inject public DefaultModelReader( ModelSourceTransformer transformer ) { @@ -78,9 +72,7 @@ public Model read( File input, Map options ) { Model model = read( in, input.toPath(), options ); - model.setPomFile( input ); - - return model; + return model.withPomFile( input.toPath() ); } } @@ -140,25 +132,13 @@ private Model read( Reader reader, Path pomFile, Map options ) InputSource source = getSource( options ); boolean strict = isStrict( options ); - try + if ( source != null ) { - if ( source != null ) - { - return readModelEx( transformingParser, source, strict ); - } - else - { - return readModel( transformingParser, strict ); - } + return readModelEx( transformingParser, source, strict ); } - catch ( InvocationTargetException e ) + else { - Throwable cause = e.getCause(); - if ( cause instanceof Exception ) - { - throw ( Exception ) cause; - } - throw e; + return readModel( transformingParser, strict ); } } catch ( XmlPullParserException e ) @@ -176,30 +156,17 @@ private Model read( Reader reader, Path pomFile, Map options ) } private Model readModel( XmlPullParser parser, boolean strict ) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException + throws XmlPullParserException, IOException { - if ( readMethod == null ) - { - readMethod = MavenXpp3Reader.class.getDeclaredMethod( "read", XmlPullParser.class, boolean.class ); - readMethod.setAccessible( true ); - } MavenXpp3Reader mr = new MavenXpp3Reader(); - Object model = readMethod.invoke( mr, parser, strict ); - return ( Model ) model; + return mr.read( parser, strict ); } private Model readModelEx( XmlPullParser parser, InputSource source, boolean strict ) - throws NoSuchMethodException, IllegalAccessException, InvocationTargetException + throws XmlPullParserException, IOException { - if ( readMethodEx == null ) - { - readMethodEx = MavenXpp3ReaderEx.class.getDeclaredMethod( "read", - XmlPullParser.class, boolean.class, InputSource.class ); - readMethodEx.setAccessible( true ); - } MavenXpp3ReaderEx mr = new MavenXpp3ReaderEx(); - Object model = readMethodEx.invoke( mr, parser, strict, source ); - return ( Model ) model; + return mr.read( parser, strict, source ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java index a6d4d984d55e..9cebee4b98d8 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java @@ -30,8 +30,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Writer; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenXpp3Writer; import org.codehaus.plexus.util.WriterFactory; /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java index 04b1a3017cdb..c6ab1cf71dfe 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelReader.java @@ -25,7 +25,8 @@ import java.io.Reader; import java.util.Map; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; /** * Handles deserialization of a model from some kind of textual format like XML. @@ -43,7 +44,7 @@ public interface ModelReader /** * The key for the option to enable tracking of line/column numbers. This option is of type - * {@link org.apache.maven.model.InputSource} and defaults to {@code null}. Providing an input source enables + * {@link InputSource} and defaults to {@code null}. Providing an input source enables * location tracking. */ String INPUT_SOURCE = "org.apache.maven.model.io.inputSource"; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java index af7e0cab30ae..0e1f41b3be9a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java @@ -25,7 +25,7 @@ import java.io.Writer; import java.util.Map; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Handles serialization of a model into some kind of textual format like XML. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java index 499f3558a0d3..9b2fb4c2e840 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java @@ -19,6 +19,7 @@ * under the License. */ +import java.util.ArrayList; import java.util.Collections; import java.util.HashMap; import java.util.List; @@ -27,10 +28,10 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -50,9 +51,9 @@ public class DefaultDependencyManagementInjector private ManagementModelMerger merger = new ManagementModelMerger(); @Override - public void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { - merger.mergeManagedDependencies( model ); + return merger.mergeManagedDependencies( model ); } /** @@ -62,7 +63,7 @@ protected static class ManagementModelMerger extends MavenModelMerger { - public void mergeManagedDependencies( Model model ) + public Model mergeManagedDependencies( Model model ) { DependencyManagement dependencyManagement = model.getDependencyManagement(); if ( dependencyManagement != null ) @@ -76,39 +77,55 @@ public void mergeManagedDependencies( Model model ) dependencies.put( key, dependency ); } + boolean modified = false; for ( Dependency managedDependency : dependencyManagement.getDependencies() ) { Object key = getDependencyKey().apply( managedDependency ); Dependency dependency = dependencies.get( key ); if ( dependency != null ) { - mergeDependency( dependency, managedDependency, false, context ); + Dependency merged = mergeDependency( dependency, managedDependency, false, context ); + if ( merged != dependency ) + { + dependencies.put( key, merged ); + modified = true; + } } } + + if ( modified ) + { + List newDeps = new ArrayList<>( dependencies.size() ); + for ( Dependency dep : model.getDependencies() ) + { + Object key = getDependencyKey().apply( dep ); + Dependency dependency = dependencies.get( key ); + newDeps.add( dependency ); + } + return Model.newBuilder( model ).dependencies( newDeps ).build(); + } } + return model; } @Override - protected void mergeDependency_Optional( Dependency target, Dependency source, boolean sourceDominant, + protected void mergeDependency_Optional( Dependency.Builder builder, + Dependency target, Dependency source, boolean sourceDominant, Map context ) { // optional flag is not managed } @Override - protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, + protected void mergeDependency_Exclusions( Dependency.Builder builder, + Dependency target, Dependency source, boolean sourceDominant, Map context ) { List tgt = target.getExclusions(); if ( tgt.isEmpty() ) { List src = source.getExclusions(); - - for ( Exclusion element : src ) - { - Exclusion clone = element.clone(); - target.addExclusion( clone ); - } + builder.exclusions( src ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java index 752b976d04ad..2bb1113eb74c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java @@ -28,12 +28,12 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.PluginManagement; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -53,9 +53,9 @@ public class DefaultPluginManagementInjector private ManagementModelMerger merger = new ManagementModelMerger(); @Override - public void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { - merger.mergeManagedBuildPlugins( model ); + return merger.mergeManagedBuildPlugins( model ); } /** @@ -65,7 +65,7 @@ protected static class ManagementModelMerger extends MavenModelMerger { - public void mergeManagedBuildPlugins( Model model ) + public Model mergeManagedBuildPlugins( Model model ) { Build build = model.getBuild(); if ( build != null ) @@ -73,18 +73,17 @@ public void mergeManagedBuildPlugins( Model model ) PluginManagement pluginManagement = build.getPluginManagement(); if ( pluginManagement != null ) { - mergePluginContainerPlugins( build, pluginManagement ); + return model.withBuild( mergePluginContainerPlugins( build, pluginManagement ) ); } } + return model; } - private void mergePluginContainerPlugins( PluginContainer target, PluginContainer source ) + private Build mergePluginContainerPlugins( Build target, PluginContainer source ) { List src = source.getPlugins(); if ( !src.isEmpty() ) { - List tgt = target.getPlugins(); - Map managedPlugins = new LinkedHashMap<>( src.size() * 2 ); Map context = Collections.emptyMap(); @@ -95,21 +94,25 @@ private void mergePluginContainerPlugins( PluginContainer target, PluginContaine managedPlugins.put( key, element ); } - for ( Plugin element : tgt ) + List newPlugins = new ArrayList<>(); + for ( Plugin element : target.getPlugins() ) { Object key = getPluginKey().apply( element ); Plugin managedPlugin = managedPlugins.get( key ); if ( managedPlugin != null ) { - mergePlugin( element, managedPlugin, false, context ); + element = mergePlugin( element, managedPlugin, false, context ); } + newPlugins.add( element ); } + return target.withPlugins( newPlugins ); } + return target; } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) + protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Plugin source, + boolean sourceDominant, Map context ) { List src = source.getExecutions(); if ( !src.isEmpty() ) @@ -122,7 +125,7 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou for ( PluginExecution element : src ) { Object key = getPluginExecutionKey().apply( element ); - merged.put( key, element.clone() ); + merged.put( key, element ); } for ( PluginExecution element : tgt ) @@ -131,12 +134,12 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou PluginExecution existing = merged.get( key ); if ( existing != null ) { - mergePluginExecution( element, existing, sourceDominant, context ); + element = mergePluginExecution( element, existing, sourceDominant, context ); } merged.put( key, element ); } - target.setExecutions( new ArrayList<>( merged.values() ) ); + builder.executions( new ArrayList<>( merged.values() ) ); } } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java index 3b70a09c9703..0b3e5277ba4f 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -39,6 +39,6 @@ public interface DependencyManagementInjector * @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}. */ - void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java index 7384fdf045f2..6b508ff96232 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -39,6 +39,6 @@ public interface PluginManagementInjector * @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}. */ - void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model injectManagement( Model model, 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 049ce1f1286b..870fd972293b 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 @@ -26,26 +26,27 @@ import java.util.Map; import java.util.Set; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DeploymentRepository; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Extension; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.IssueManagement; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Repository; -import org.apache.maven.model.RepositoryBase; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.CiManagement; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DeploymentRepository; +import org.apache.maven.api.model.DistributionManagement; +import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.Extension; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.IssueManagement; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Organization; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.ReportSet; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.model.RepositoryBase; +import org.apache.maven.api.model.Scm; +import org.apache.maven.api.model.Site; +import org.apache.maven.model.v4.ModelMerger; import org.codehaus.plexus.util.StringUtils; /** @@ -55,7 +56,7 @@ * @author Benjamin Bentmann */ public class MavenModelMerger - extends ModelMerger + extends ModelMerger { /** @@ -69,42 +70,44 @@ public class MavenModelMerger public static final String ARTIFACT_ID = "artifact-id"; @Override - protected void mergeModel( Model target, Model source, boolean sourceDominant, Map context ) + protected Model mergeModel( Model target, Model source, boolean sourceDominant, Map context ) { context.put( ARTIFACT_ID, target.getArtifactId() ); - super.mergeModel( target, source, sourceDominant, context ); + return super.mergeModel( target, source, sourceDominant, context ); } @Override - protected void mergeModel_Name( Model target, Model source, boolean sourceDominant, Map context ) + protected void mergeModel_Name( Model.Builder builder, Model target, Model source, + boolean sourceDominant, Map context ) { String src = source.getName(); if ( src != null ) { if ( sourceDominant ) { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); + builder.name( src ); + builder.location( "name", source.getLocation( "name" ) ); } } } @Override - protected void mergeModel_Url( Model target, Model source, boolean sourceDominant, Map context ) + protected void mergeModel_Url( Model.Builder builder, Model target, Model source, + boolean sourceDominant, Map context ) { String src = source.getUrl(); if ( src != null ) { if ( sourceDominant ) { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( src ); + builder.location( "url", source.getLocation( "url" ) ); } else if ( target.getUrl() == null ) { - target.setUrl( extrapolateChildUrl( src, source.isChildProjectUrlInheritAppendPath(), context ) ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( extrapolateChildUrl( src, source.isChildProjectUrlInheritAppendPath(), context ) ); + builder.location( "url", source.getLocation( "url" ) ); } } } @@ -114,7 +117,7 @@ else if ( target.getUrl() == null ) * merger */ @Override - protected void mergeModel_Organization( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Organization( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { Organization src = source.getOrganization(); @@ -123,17 +126,15 @@ protected void mergeModel_Organization( Model target, Model source, boolean sour Organization tgt = target.getOrganization(); if ( tgt == null ) { - tgt = new Organization(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setOrganization( tgt ); - mergeOrganization( tgt, src, sourceDominant, context ); + builder.organization( src ); + builder.location( "organisation", source.getLocation( "organisation" ) ); } } } @Override - protected void mergeModel_IssueManagement( Model target, Model source, boolean sourceDominant, - Map context ) + protected void mergeModel_IssueManagement( Model.Builder builder, Model target, Model source, + boolean sourceDominant, Map context ) { IssueManagement src = source.getIssueManagement(); if ( src != null ) @@ -141,16 +142,14 @@ protected void mergeModel_IssueManagement( Model target, Model source, boolean s IssueManagement tgt = target.getIssueManagement(); if ( tgt == null ) { - tgt = new IssueManagement(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setIssueManagement( tgt ); - mergeIssueManagement( tgt, src, sourceDominant, context ); + builder.issueManagement( src ); + builder.location( "issueManagement", source.getLocation( "issueManagement" ) ); } } } @Override - protected void mergeModel_CiManagement( Model target, Model source, boolean sourceDominant, + protected void mergeModel_CiManagement( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { CiManagement src = source.getCiManagement(); @@ -159,85 +158,75 @@ protected void mergeModel_CiManagement( Model target, Model source, boolean sour CiManagement tgt = target.getCiManagement(); if ( tgt == null ) { - tgt = new CiManagement(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setCiManagement( tgt ); - mergeCiManagement( tgt, src, sourceDominant, context ); + builder.ciManagement( src ); + builder.location( "ciManagement", source.getLocation( "ciManagement" ) ); } } } @Override - protected void mergeModel_ModelVersion( Model target, Model source, boolean sourceDominant, + protected void mergeModel_ModelVersion( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_ArtifactId( Model target, Model source, boolean sourceDominant, + protected void mergeModel_ArtifactId( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Profiles( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_Prerequisites( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Prerequisites( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { // neither inherited nor injected } @Override - protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Licenses( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { - if ( target.getLicenses().isEmpty() ) - { - target.setLicenses( new ArrayList<>( source.getLicenses() ) ); - } + builder.licenses( target.getLicenses().isEmpty() ? source.getLicenses() : target.getLicenses() ); } @Override - protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Developers( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { - if ( target.getDevelopers().isEmpty() ) - { - target.setDevelopers( new ArrayList<>( source.getDevelopers() ) ); - } + builder.developers( target.getDevelopers().isEmpty() ? source.getDevelopers() : target.getDevelopers() ); } @Override - protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant, + protected void mergeModel_Contributors( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { - if ( target.getContributors().isEmpty() ) - { - target.setContributors( new ArrayList<>( source.getContributors() ) ); - } + builder.contributors( target.getContributors().isEmpty() + ? source.getContributors() : target.getContributors() ); } @Override - protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant, + protected void mergeModel_MailingLists( Model.Builder builder, Model target, Model source, boolean sourceDominant, Map context ) { if ( target.getMailingLists().isEmpty() ) { - target.setMailingLists( new ArrayList<>( source.getMailingLists() ) ); + builder.mailingLists( new ArrayList<>( source.getMailingLists() ) ); } } @Override - protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) + protected void mergeModelBase_Modules( ModelBase.Builder builder, ModelBase target, ModelBase source, + boolean sourceDominant, Map context ) { List src = source.getModules(); if ( !src.isEmpty() && sourceDominant ) @@ -260,8 +249,8 @@ protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boole indices.add( ~i ); } } - target.setModules( merged ); - target.setLocation( "modules", InputLocation.merge( target.getLocation( "modules" ), + builder.modules( merged ); + builder.location( "modules", InputLocation.merge( target.getLocation( "modules" ), source.getLocation( "modules" ), indices ) ); } } @@ -271,8 +260,8 @@ protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boole * source-first, dominant-first, recessive-first */ @Override - protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) + protected void mergeModelBase_Repositories( ModelBase.Builder builder, ModelBase target, ModelBase source, + boolean sourceDominant, Map context ) { List src = source.getRepositories(); if ( !src.isEmpty() ) @@ -307,13 +296,13 @@ protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, } } - target.setRepositories( new ArrayList<>( merged.values() ) ); + builder.repositories( new ArrayList<>( merged.values() ) ); } } @Override - protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) + protected void mergeModelBase_PluginRepositories( ModelBase.Builder builder, ModelBase target, ModelBase source, + boolean sourceDominant, Map context ) { List src = source.getPluginRepositories(); if ( !src.isEmpty() ) @@ -348,7 +337,7 @@ protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase so } } - target.setPluginRepositories( new ArrayList<>( merged.values() ) ); + builder.pluginRepositories( new ArrayList<>( merged.values() ) ); } } @@ -356,8 +345,8 @@ protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase so * TODO: Whether duplicates should be removed looks like an option for the generated merger. */ @Override - protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) + protected void mergeBuildBase_Filters( BuildBase.Builder builder, BuildBase target, BuildBase source, + boolean sourceDominant, Map context ) { List src = source.getFilters(); if ( !src.isEmpty() ) @@ -373,33 +362,38 @@ protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boole merged.add( s ); } } - target.setFilters( merged ); + builder.filters( merged ); } } @Override - protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) + protected void mergeBuildBase_Resources( BuildBase.Builder builder, BuildBase target, BuildBase source, + boolean sourceDominant, Map context ) { if ( sourceDominant || target.getResources().isEmpty() ) { - super.mergeBuildBase_Resources( target, source, sourceDominant, context ); + super.mergeBuildBase_Resources( builder, target, source, sourceDominant, context ); } } @Override - protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant, + protected void mergeBuildBase_TestResources( BuildBase.Builder builder, + BuildBase target, + BuildBase source, + boolean sourceDominant, Map context ) { if ( sourceDominant || target.getTestResources().isEmpty() ) { - super.mergeBuildBase_TestResources( target, source, sourceDominant, context ); + super.mergeBuildBase_TestResources( builder, target, source, sourceDominant, context ); } } @Override - protected void mergeDistributionManagement_Repository( DistributionManagement target, - DistributionManagement source, boolean sourceDominant, + protected void mergeDistributionManagement_Repository( DistributionManagement.Builder builder, + DistributionManagement target, + DistributionManagement source, + boolean sourceDominant, Map context ) { DeploymentRepository src = source.getRepository(); @@ -408,16 +402,15 @@ protected void mergeDistributionManagement_Repository( DistributionManagement ta DeploymentRepository tgt = target.getRepository(); if ( sourceDominant || tgt == null ) { - tgt = new DeploymentRepository(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setRepository( tgt ); - mergeDeploymentRepository( tgt, src, sourceDominant, context ); + tgt = DeploymentRepository.newInstance( false ); + builder.repository( mergeDeploymentRepository( tgt, src, sourceDominant, context ) ); } } } @Override - protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target, + protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement.Builder builder, + DistributionManagement target, DistributionManagement source, boolean sourceDominant, Map context ) @@ -428,42 +421,41 @@ protected void mergeDistributionManagement_SnapshotRepository( DistributionManag DeploymentRepository tgt = target.getSnapshotRepository(); if ( sourceDominant || tgt == null ) { - tgt = new DeploymentRepository(); - tgt.setLocation( "", src.getLocation( "" ) ); - target.setSnapshotRepository( tgt ); - mergeDeploymentRepository( tgt, src, sourceDominant, context ); + tgt = DeploymentRepository.newInstance( false ); + builder.snapshotRepository( mergeDeploymentRepository( tgt, src, sourceDominant, context ) ); } } } @Override - protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) + protected void mergeDistributionManagement_Site( DistributionManagement.Builder builder, + DistributionManagement target, + DistributionManagement source, + boolean sourceDominant, + Map context ) { Site src = source.getSite(); if ( src != null ) { Site tgt = target.getSite(); + if ( tgt == null ) + { + tgt = Site.newBuilder( false ).build(); + } + Site.Builder sbuilder = Site.newBuilder( tgt ); if ( sourceDominant || tgt == null || isSiteEmpty( tgt ) ) { - if ( tgt == null ) - { - tgt = new Site(); - } - tgt.setLocation( "", src.getLocation( "" ) ); - target.setSite( tgt ); - mergeSite( tgt, src, sourceDominant, context ); + mergeSite( sbuilder, tgt, src, sourceDominant, context ); } - mergeSite_ChildSiteUrlInheritAppendPath( tgt, src, sourceDominant, context ); + super.mergeSite_ChildSiteUrlInheritAppendPath( sbuilder, tgt, src, sourceDominant, context ); + builder.site( sbuilder.build() ); } } @Override - protected void mergeSite( Site target, Site source, boolean sourceDominant, Map context ) + protected void mergeSite_ChildSiteUrlInheritAppendPath( Site.Builder builder, Site target, Site source, + boolean sourceDominant, Map context ) { - mergeSite_Id( target, source, sourceDominant, context ); - mergeSite_Name( target, source, sourceDominant, context ); - mergeSite_Url( target, source, sourceDominant, context ); } protected boolean isSiteEmpty( Site site ) @@ -473,87 +465,90 @@ protected boolean isSiteEmpty( Site site ) } @Override - protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map context ) + protected void mergeSite_Url( Site.Builder builder, Site target, Site source, + boolean sourceDominant, Map context ) { String src = source.getUrl(); if ( src != null ) { if ( sourceDominant ) { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( src ); + builder.location( "url", source.getLocation( "url" ) ); } else if ( target.getUrl() == null ) { - target.setUrl( extrapolateChildUrl( src, source.isChildSiteUrlInheritAppendPath(), context ) ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( extrapolateChildUrl( src, source.isChildSiteUrlInheritAppendPath(), context ) ); + builder.location( "url", source.getLocation( "url" ) ); } } } @Override - protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map context ) + protected void mergeScm_Url( Scm.Builder builder, Scm target, Scm source, + boolean sourceDominant, Map context ) { String src = source.getUrl(); if ( src != null ) { if ( sourceDominant ) { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( src ); + builder.location( "url", source.getLocation( "url" ) ); } else if ( target.getUrl() == null ) { - target.setUrl( extrapolateChildUrl( src, source.isChildScmUrlInheritAppendPath(), context ) ); - target.setLocation( "url", source.getLocation( "url" ) ); + builder.url( extrapolateChildUrl( src, source.isChildScmUrlInheritAppendPath(), context ) ); + builder.location( "url", source.getLocation( "url" ) ); } } } @Override - protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map context ) + protected void mergeScm_Connection( Scm.Builder builder, Scm target, Scm source, + boolean sourceDominant, Map context ) { String src = source.getConnection(); if ( src != null ) { if ( sourceDominant ) { - target.setConnection( src ); - target.setLocation( "connection", source.getLocation( "connection" ) ); + builder.connection( src ); + builder.location( "connection", source.getLocation( "connection" ) ); } else if ( target.getConnection() == null ) { - target.setConnection( extrapolateChildUrl( src, source.isChildScmConnectionInheritAppendPath(), + builder.connection( extrapolateChildUrl( src, source.isChildScmConnectionInheritAppendPath(), context ) ); - target.setLocation( "connection", source.getLocation( "connection" ) ); + builder.location( "connection", source.getLocation( "connection" ) ); } } } @Override - protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant, - Map context ) + protected void mergeScm_DeveloperConnection( Scm.Builder builder, Scm target, Scm source, + boolean sourceDominant, Map context ) { String src = source.getDeveloperConnection(); if ( src != null ) { if ( sourceDominant ) { - target.setDeveloperConnection( src ); - target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) ); + builder.developerConnection( src ); + builder.location( "developerConnection", source.getLocation( "developerConnection" ) ); } else if ( target.getDeveloperConnection() == null ) { String e = extrapolateChildUrl( src, source.isChildScmDeveloperConnectionInheritAppendPath(), context ); - target.setDeveloperConnection( e ); - target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) ); + builder.developerConnection( e ); + builder.location( "developerConnection", source.getLocation( "developerConnection" ) ); } } } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) + protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Plugin source, + boolean sourceDominant, Map context ) { List src = source.getExecutions(); if ( !src.isEmpty() ) @@ -578,17 +573,18 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou PluginExecution existing = merged.get( key ); if ( existing != null ) { - mergePluginExecution( element, existing, sourceDominant, context ); + element = mergePluginExecution( element, existing, sourceDominant, context ); } merged.put( key, element ); } - target.setExecutions( new ArrayList<>( merged.values() ) ); + builder.executions( new ArrayList<>( merged.values() ) ); } } @Override - protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant, + protected void mergePluginExecution_Goals( PluginExecution.Builder builder, PluginExecution target, + PluginExecution source, boolean sourceDominant, Map context ) { List src = source.getGoals(); @@ -605,12 +601,13 @@ protected void mergePluginExecution_Goals( PluginExecution target, PluginExecuti merged.add( s ); } } - target.setGoals( merged ); + builder.goals( merged ); } } @Override - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, + protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, ReportPlugin target, + ReportPlugin source, boolean sourceDominant, Map context ) { List src = source.getReportSets(); @@ -639,7 +636,7 @@ protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin s merged.put( key, element ); } - target.setReportSets( new ArrayList<>( merged.values() ) ); + builder.reportSets( new ArrayList<>( merged.values() ) ); } } 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 9f86c0997eac..01bfe0d2718c 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 @@ -24,14 +24,15 @@ import java.util.LinkedHashMap; import java.util.List; import java.util.Map; +import java.util.function.Function; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -51,8 +52,10 @@ public class DefaultModelNormalizer private DuplicateMerger merger = new DuplicateMerger(); @Override - public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { + Model.Builder builder = Model.newBuilder( model ); + Build build = model.getBuild(); if ( build != null ) { @@ -65,14 +68,16 @@ public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelPro Plugin first = normalized.get( key ); if ( first != null ) { - merger.mergePlugin( plugin, first ); + plugin = merger.mergePlugin( plugin, first ); } normalized.put( key, plugin ); } if ( plugins.size() != normalized.size() ) { - build.setPlugins( new ArrayList<>( normalized.values() ) ); + builder.build( Build.newBuilder( build ) + .plugins( new ArrayList<>( normalized.values() ) ) + .build() ); } } @@ -93,8 +98,10 @@ public void mergeDuplicates( Model model, ModelBuildingRequest request, ModelPro if ( dependencies.size() != normalized.size() ) { - model.setDependencies( new ArrayList<>( normalized.values() ) ); + builder.dependencies( new ArrayList<>( normalized.values() ) ); } + + return builder.build(); } /** @@ -104,38 +111,64 @@ protected static class DuplicateMerger extends MavenModelMerger { - public void mergePlugin( Plugin target, Plugin source ) + public Plugin mergePlugin( Plugin target, Plugin source ) { - super.mergePlugin( target, source, false, Collections.emptyMap() ); + return super.mergePlugin( target, source, false, Collections.emptyMap() ); } } @Override - public void injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { - injectDependencyDefaults( model.getDependencies() ); + Model.Builder builder = Model.newBuilder( model ); + builder.dependencies( injectList( model.getDependencies(), this::injectDependency ) ); Build build = model.getBuild(); if ( build != null ) { - for ( Plugin plugin : build.getPlugins() ) - { - injectDependencyDefaults( plugin.getDependencies() ); - } + Build newBuild = Build.newBuilder( build ) + .plugins( injectList( build.getPlugins(), this::injectPlugin ) ) + .build(); + builder.build( newBuild != build ? newBuild : null ); } + + return builder.build(); } - private void injectDependencyDefaults( List dependencies ) + private Plugin injectPlugin( Plugin p ) { - for ( Dependency dependency : dependencies ) + return Plugin.newBuilder( p ) + .dependencies( injectList( p.getDependencies(), this::injectDependency ) ) + .build(); + } + + 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; + } + + /** + * Returns a list suited for the builders, i.e. null if not modified + */ + private List injectList( List list, Function modifer ) + { + List newList = null; + for ( int i = 0; i < list.size(); i++ ) { - if ( StringUtils.isEmpty( dependency.getScope() ) ) + T oldT = list.get( i ); + T newT = modifer.apply( oldT ); + if ( newT != oldT ) { - // we cannot set this directly in the MDO due to the interactions with dependency management - dependency.setScope( "compile" ); + if ( newList == null ) + { + newList = new ArrayList<>( list ); + } + newList.set( i, newT ); } - } + } + return newList; } } 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 7cab86b65cc3..ff73a55ef92a 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 @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -39,7 +39,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}. */ - void mergeDuplicates( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model 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 @@ -49,6 +49,6 @@ 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}. */ - void injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model injectDefaultValues( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java index 801499f6cace..2c9b5b1ce347 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java @@ -22,15 +22,17 @@ import java.io.File; import java.util.ArrayList; import java.util.List; +import java.util.Objects; +import java.util.function.Function; import javax.inject.Inject; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Resource; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Reporting; +import org.apache.maven.api.model.Resource; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -53,61 +55,87 @@ public DefaultModelPathTranslator( PathTranslator pathTranslator ) } @Override - public void alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ) + public Model alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ) { if ( model == null || basedir == null ) { - return; + return model; } Build build = model.getBuild(); - + Build newBuild = null; if ( build != null ) { - build.setDirectory( alignToBaseDirectory( build.getDirectory(), basedir ) ); - - build.setSourceDirectory( alignToBaseDirectory( build.getSourceDirectory(), basedir ) ); - - build.setTestSourceDirectory( alignToBaseDirectory( build.getTestSourceDirectory(), basedir ) ); - - build.setScriptSourceDirectory( alignToBaseDirectory( build.getScriptSourceDirectory(), basedir ) ); - - for ( Resource resource : build.getResources() ) - { - resource.setDirectory( alignToBaseDirectory( resource.getDirectory(), basedir ) ); - } + newBuild = Build.newBuilder( build ) + .directory( alignToBaseDirectory( build.getDirectory(), basedir ) ) + .sourceDirectory( alignToBaseDirectory( build.getSourceDirectory(), basedir ) ) + .testSourceDirectory( alignToBaseDirectory( build.getTestSourceDirectory(), basedir ) ) + .scriptSourceDirectory( alignToBaseDirectory( build.getScriptSourceDirectory(), basedir ) ) + .resources( map( build.getResources(), r -> alignToBaseDirectory( r, basedir ) ) ) + .testResources( map( build.getTestResources(), r -> alignToBaseDirectory( r, basedir ) ) ) + .filters( map( build.getFilters(), s -> alignToBaseDirectory( s, basedir ) ) ) + .outputDirectory( alignToBaseDirectory( build.getOutputDirectory(), basedir ) ) + .testOutputDirectory( alignToBaseDirectory( build.getTestOutputDirectory(), basedir ) ) + .build(); + } - for ( Resource resource : build.getTestResources() ) - { - resource.setDirectory( alignToBaseDirectory( resource.getDirectory(), basedir ) ); - } + Reporting reporting = model.getReporting(); + Reporting newReporting = null; + if ( reporting != null ) + { + newReporting = Reporting.newBuilder( reporting ) + .outputDirectory( alignToBaseDirectory( reporting.getOutputDirectory(), basedir ) ) + .build(); + } + if ( newBuild != build || newReporting != reporting ) + { + return Model.newBuilder( model ) + .build( newBuild ) + .reporting( newReporting ) + .build(); + } + return model; + } - if ( build.getFilters() != null ) + private List map( List resources, Function mapper ) + { + List newResources = null; + if ( resources != null ) + { + for ( int i = 0; i < resources.size(); i++ ) { - List filters = new ArrayList<>( build.getFilters().size() ); - for ( String filter : build.getFilters() ) + T resource = resources.get( i ); + T newResource = mapper.apply( resource ); + if ( newResource != null ) { - filters.add( alignToBaseDirectory( filter, basedir ) ); + if ( newResources == null ) + { + newResources = new ArrayList<>( resources ); + } + newResources.set( i, newResource ); } - build.setFilters( filters ); } - - build.setOutputDirectory( alignToBaseDirectory( build.getOutputDirectory(), basedir ) ); - - build.setTestOutputDirectory( alignToBaseDirectory( build.getTestOutputDirectory(), basedir ) ); } + return newResources; + } - Reporting reporting = model.getReporting(); - - if ( reporting != null ) + private Resource alignToBaseDirectory( Resource resource, File basedir ) + { + if ( resource != null ) { - reporting.setOutputDirectory( alignToBaseDirectory( reporting.getOutputDirectory(), basedir ) ); + String newDir = alignToBaseDirectory( resource.getDirectory(), basedir ); + if ( newDir != null ) + { + return resource.withDirectory( newDir ); + } } + return resource; } private String alignToBaseDirectory( String path, File basedir ) { - return pathTranslator.alignToBaseDirectory( path, basedir ); + String newPath = pathTranslator.alignToBaseDirectory( path, basedir ); + return Objects.equals( path, newPath ) ? null : newPath; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java index 92d7bbd3165b..58a7fbd9097b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java @@ -23,10 +23,12 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Model; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; +import java.util.Objects; + +import org.apache.maven.api.model.DistributionManagement; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Scm; +import org.apache.maven.api.model.Site; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -50,21 +52,29 @@ public DefaultModelUrlNormalizer( UrlNormalizer urlNormalizer ) } @Override - public void normalize( Model model, ModelBuildingRequest request ) + public Model normalize( Model model, ModelBuildingRequest request ) { if ( model == null ) { - return; + return null; } - model.setUrl( normalize( model.getUrl() ) ); + Model.Builder builder = Model.newBuilder( model ); + + builder.url( normalize( model.getUrl() ) ); Scm scm = model.getScm(); if ( scm != null ) { - scm.setUrl( normalize( scm.getUrl() ) ); - scm.setConnection( normalize( scm.getConnection() ) ); - scm.setDeveloperConnection( normalize( scm.getDeveloperConnection() ) ); + scm = Scm.newBuilder( scm ) + .url( normalize( scm.getUrl() ) ) + .connection( normalize( scm.getConnection() ) ) + .developerConnection( normalize( scm.getDeveloperConnection() ) ) + .build(); + if ( scm != model.getScm() ) + { + builder.scm( scm ); + } } DistributionManagement dist = model.getDistributionManagement(); @@ -73,14 +83,23 @@ public void normalize( Model model, ModelBuildingRequest request ) Site site = dist.getSite(); if ( site != null ) { - site.setUrl( normalize( site.getUrl() ) ); + site = Site.newBuilder( site ) + .url( normalize( site.getUrl() ) ) + .build(); + if ( site != dist.getSite() ) + { + builder.distributionManagement( dist.withSite( site ) ); + } } } + + return builder.build(); } private String normalize( String url ) { - return urlNormalizer.normalize( url ); + String newUrl = urlNormalizer.normalize( url ); + return Objects.equals( url, newUrl ) ? null : newUrl; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java index 2bd39c5501ff..1d73a591257a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java @@ -21,7 +21,7 @@ import java.io.File; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -40,6 +40,6 @@ public interface ModelPathTranslator * @param basedir The base directory to resolve relative paths against, may be {@code null}. * @param request The model building request that holds further settings, must not be {@code null}. */ - void alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ); + Model alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java index 8325b05d35f4..33b2998cdb01 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -37,6 +37,6 @@ public interface ModelUrlNormalizer * @param model The model whose URLs should be normalized, may be {@code null}. * @param request The model building request that holds further settings, must not be {@code null}. */ - void normalize( Model model, ModelBuildingRequest request ); + Model normalize( Model model, ModelBuildingRequest request ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java index 41257ac3e9d1..2560f3c9aa0e 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/ProfileActivationFilePathInterpolator.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.ActivationFile; +import org.apache.maven.api.model.ActivationFile; import org.apache.maven.model.profile.ProfileActivationContext; import org.codehaus.plexus.interpolation.AbstractValueSource; import org.codehaus.plexus.interpolation.InterpolationException; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java index 012a6852a6b1..ba88dd19d7b1 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java @@ -19,19 +19,20 @@ * under the License. */ +import java.util.ArrayList; import java.util.List; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.PluginManagement; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Handles expansion of general build plugin configuration into individual executions. @@ -45,42 +46,61 @@ public class DefaultPluginConfigurationExpander { @Override - public void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { Build build = model.getBuild(); if ( build != null ) { - expand( build.getPlugins() ); + Build.Builder builder = Build.newBuilder( build ); + + builder.plugins( expand( build.getPlugins() ) ); PluginManagement pluginManagement = build.getPluginManagement(); if ( pluginManagement != null ) { - expand( pluginManagement.getPlugins() ); + builder.pluginManagement( pluginManagement.withPlugins( expand( pluginManagement.getPlugins() ) ) ); } + + return model.withBuild( builder.build() ); } + + return model; } - private void expand( List plugins ) + private List expand( List plugins ) { + List newPlugins = new ArrayList<>( plugins.size() ); + for ( Plugin plugin : plugins ) { - Xpp3Dom pluginConfiguration = (Xpp3Dom) plugin.getConfiguration(); + Dom parentDom = plugin.getConfiguration(); - if ( pluginConfiguration != null ) + if ( parentDom != null ) { + List executions = new ArrayList<>( plugin.getExecutions().size() ); for ( PluginExecution execution : plugin.getExecutions() ) { - Xpp3Dom executionConfiguration = (Xpp3Dom) execution.getConfiguration(); - - executionConfiguration = - Xpp3Dom.mergeXpp3Dom( executionConfiguration, new Xpp3Dom( pluginConfiguration ) ); - - execution.setConfiguration( executionConfiguration ); + Dom childDom = execution.getConfiguration(); + if ( childDom != null ) + { + childDom.merge( parentDom ); + } + else + { + childDom = parentDom.clone(); + } + executions.add( execution.withConfiguration( + childDom != null ? childDom.merge( parentDom ) : parentDom ) ); } + plugin = plugin.withExecutions( executions ); } + + newPlugins.add( plugin ); } + + return newPlugins; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java index b221ac23dda6..a6fcef68c334 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java @@ -22,13 +22,16 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Model; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; +import java.util.ArrayList; +import java.util.List; + +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.ReportSet; +import org.apache.maven.api.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Handles expansion of general report plugin configuration into individual report sets. @@ -42,27 +45,33 @@ public class DefaultReportConfigurationExpander { @Override - public void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { Reporting reporting = model.getReporting(); if ( reporting != null ) { + List reportPlugins = new ArrayList<>(); for ( ReportPlugin reportPlugin : reporting.getPlugins() ) { - Xpp3Dom parentDom = (Xpp3Dom) reportPlugin.getConfiguration(); - + Dom parentDom = reportPlugin.getConfiguration(); if ( parentDom != null ) { - for ( ReportSet execution : reportPlugin.getReportSets() ) + List reportSets = new ArrayList<>(); + for ( ReportSet reportSet : reportPlugin.getReportSets() ) { - Xpp3Dom childDom = (Xpp3Dom) execution.getConfiguration(); - childDom = Xpp3Dom.mergeXpp3Dom( childDom, new Xpp3Dom( parentDom ) ); - execution.setConfiguration( childDom ); + Dom childDom = reportSet.getConfiguration(); + Dom newDom = childDom != null ? childDom.merge( parentDom ) : parentDom; + reportSets.add( reportSet.withConfiguration( newDom ) ); } + reportPlugin = reportPlugin.withReportSets( reportSets ); } + reportPlugins.add( reportPlugin ); } + return model.withReporting( reporting.withPlugins( reportPlugins ) ); } + + return model; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java index 04b414b01cb5..3f109f6b90c7 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java @@ -22,22 +22,27 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Build; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; +import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; +import java.util.List; + +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.Xpp3Dom; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginManagement; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.ReportSet; +import org.apache.maven.api.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblemCollectorRequest; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; -import org.codehaus.plexus.util.StringUtils; -import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Handles conversion of the <reporting> section into the configuration of Maven Site Plugin 3.x, @@ -54,58 +59,48 @@ public class DefaultReportingConverter { String modelId = "org.apache.maven:maven-model-builder:" + this.getClass().getPackage().getImplementationVersion() + ":reporting-converter"; - InputSource inputSource = new InputSource(); - inputSource.setModelId( modelId ); + InputSource inputSource = new InputSource( modelId, null ); location = new InputLocation( -1, -1, inputSource ); - location.setLocation( 0, location ); } @Override - public void convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public Model convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { Reporting reporting = model.getReporting(); if ( reporting == null ) { - return; + return model; } + Model.Builder builder = Model.newBuilder( model ); + Build build = model.getBuild(); if ( build == null ) { - build = new Build(); - model.setBuild( build ); - model.setLocation( "build", location ); + build = Build.newInstance(); + builder.location( "build", location ); } Plugin sitePlugin = findSitePlugin( build ); - if ( sitePlugin == null ) { - sitePlugin = new Plugin(); - sitePlugin.setArtifactId( "maven-site-plugin" ); - sitePlugin.setLocation( "artifactId", location ); - PluginManagement pluginManagement = build.getPluginManagement(); - if ( pluginManagement == null ) - { - pluginManagement = new PluginManagement(); - build.setPluginManagement( pluginManagement ); - } - pluginManagement.addPlugin( sitePlugin ); + sitePlugin = Plugin.newBuilder() + .artifactId( "maven-site-plugin" ) + .location( "artifactId", location ) + .build(); } - Xpp3Dom configuration = (Xpp3Dom) sitePlugin.getConfiguration(); - + Dom configuration = sitePlugin.getConfiguration(); if ( configuration == null ) { - configuration = new Xpp3Dom( "configuration", location ); - sitePlugin.setConfiguration( configuration ); + configuration = newDom( "", "", location ); } - Xpp3Dom reportPlugins = configuration.getChild( "reportPlugins" ); + List configChildren = new ArrayList<>( configuration.getChildren() ); - if ( reportPlugins != null ) + if ( configuration.getChild( "reportPlugins" ) != null ) { // new-style report configuration already present: warn since this new style has been deprecated // in favor of classical reporting section MSITE-647 / MSITE-684 @@ -113,17 +108,16 @@ public void convertReporting( Model model, ModelBuildingRequest request, ModelPr .setMessage( "Reporting configuration should be done in section, " + "not in maven-site-plugin as reportPlugins parameter." ) .setLocation( sitePlugin.getLocation( "configuration" ) ) ); - return; + return model; } if ( configuration.getChild( "outputDirectory" ) == null ) { - addDom( configuration, "outputDirectory", reporting.getOutputDirectory(), - reporting.getLocation( "outputDirectory" ) ); + configChildren.add( newDom( "outputDirectory", reporting.getOutputDirectory(), + reporting.getLocation( "outputDirectory" ) ) ); } - reportPlugins = new Xpp3Dom( "reportPlugins", location ); - configuration.addChild( reportPlugins ); + List reportPlugins = new ArrayList<>(); boolean hasMavenProjectInfoReportsPlugin = false; @@ -140,8 +134,8 @@ public void convertReporting( Model model, ModelBuildingRequest request, ModelPr for ( ReportPlugin plugin : reporting.getPlugins() ) { - Xpp3Dom reportPlugin = convert( plugin ); - reportPlugins.addChild( reportPlugin ); + Dom reportPlugin = convert( plugin ); + reportPlugins.add( reportPlugin ); if ( !reporting.isExcludeDefaults() && !hasMavenProjectInfoReportsPlugin && "org.apache.maven.plugins".equals( plugin.getGroupId() ) @@ -153,13 +147,37 @@ public void convertReporting( Model model, ModelBuildingRequest request, ModelPr if ( !reporting.isExcludeDefaults() && !hasMavenProjectInfoReportsPlugin ) { - Xpp3Dom dom = new Xpp3Dom( "reportPlugin", location ); + Xpp3Dom dom = newDom( "reportPlugin", + Arrays.asList( + newDom( "groupId", "org.apache.maven.plugins", null ), + newDom( "artifactId", "maven-project-info-reports-plugin", null ) + ), + location ); + + reportPlugins.add( dom ); + } - addDom( dom, "groupId", "org.apache.maven.plugins" ); - addDom( dom, "artifactId", "maven-project-info-reports-plugin" ); + configChildren.add( newDom( "reportPlugins", reportPlugins, location ) ); + configuration = newDom( "configuration", configChildren, location ); - reportPlugins.addChild( dom ); + sitePlugin = sitePlugin.withConfiguration( configuration ); + + PluginManagement pluginManagement = build.getPluginManagement(); + if ( pluginManagement == null ) + { + pluginManagement = PluginManagement.newBuilder() + .plugins( Collections.singletonList( sitePlugin ) ) + .build(); + } + else + { + List plugins = new ArrayList<>( pluginManagement.getPlugins() ); + plugins.add( sitePlugin ); + pluginManagement = pluginManagement.withPlugins( plugins ); } + build = build.withPluginManagement( pluginManagement ); + + return builder.build( build ).build(); } private Plugin findSitePlugin( Build build ) @@ -193,82 +211,73 @@ private boolean isSitePlugin( Plugin plugin ) && "org.apache.maven.plugins".equals( plugin.getGroupId() ); } - private Xpp3Dom convert( ReportPlugin plugin ) + private Dom convert( ReportPlugin plugin ) { - Xpp3Dom dom = new Xpp3Dom( "reportPlugin", plugin.getLocation( "" ) ); + List children = new ArrayList<>(); - addDom( dom, "groupId", plugin.getGroupId(), plugin.getLocation( "groupId" ) ); - addDom( dom, "artifactId", plugin.getArtifactId(), plugin.getLocation( "artifactId" ) ); - addDom( dom, "version", plugin.getVersion(), plugin.getLocation( "version" ) ); + children.add( newDom( "groupId", plugin.getGroupId(), plugin.getLocation( "groupId" ) ) ); + children.add( newDom( "artifactId", plugin.getArtifactId(), plugin.getLocation( "artifactId" ) ) ); + children.add( newDom( "version", plugin.getVersion(), plugin.getLocation( "version" ) ) ); - Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration(); + Dom configuration = plugin.getConfiguration(); if ( configuration != null ) { - configuration = new Xpp3Dom( configuration ); - dom.addChild( configuration ); + children.add( configuration ); } if ( !plugin.getReportSets().isEmpty() ) { - Xpp3Dom reportSets = new Xpp3Dom( "reportSets", plugin.getLocation( "reportSets" ) ); + List reportSets = new ArrayList<>(); for ( ReportSet reportSet : plugin.getReportSets() ) { - Xpp3Dom rs = convert( reportSet ); - reportSets.addChild( rs ); + Dom rs = convert( reportSet ); + reportSets.add( rs ); } - dom.addChild( reportSets ); + children.add( newDom( "reportSets", reportSets, plugin.getLocation( "reportSets" ) ) ); } - return dom; + return newDom( "reportPlugin", children, plugin.getLocation( "" ) ); } - private Xpp3Dom convert( ReportSet reportSet ) + private Dom convert( ReportSet reportSet ) { - Xpp3Dom dom = new Xpp3Dom( "reportSet", reportSet.getLocation( "" ) ); + List children = new ArrayList<>(); - InputLocation idLocation = reportSet.getLocation( "id" ); - addDom( dom, "id", reportSet.getId(), idLocation == null ? location : idLocation ); + if ( reportSet.getId() != null ) + { + InputLocation idLocation = reportSet.getLocation( "id" ); + children.add( newDom( "id", reportSet.getId(), idLocation == null ? location : idLocation ) ); + } - Xpp3Dom configuration = (Xpp3Dom) reportSet.getConfiguration(); + Dom configuration = reportSet.getConfiguration(); if ( configuration != null ) { - configuration = new Xpp3Dom( configuration ); - dom.addChild( configuration ); + children.add( configuration ); } if ( !reportSet.getReports().isEmpty() ) { InputLocation location = reportSet.getLocation( "reports" ); - Xpp3Dom reports = new Xpp3Dom( "reports", location ); - int n = 0; - for ( String report : reportSet.getReports() ) + List reports = new ArrayList<>(); + for ( int n = 0; n < reportSet.getReports().size(); n++ ) { - addDom( reports, "report", report, ( location == null ) ? null : location.getLocation( n++ ) ); + String report = reportSet.getReports().get( n ); + reports.add( newDom( "report", report, location != null ? location.getLocation( n ) : null ) ); } - dom.addChild( reports ); + children.add( newDom( "reports", reports, location ) ); } - return dom; - } - - private void addDom( Xpp3Dom parent, String childName, String childValue ) - { - addDom( parent, childName, childValue, location ); + return newDom( "reportSet", children, reportSet.getLocation( "" ) ); } - private void addDom( Xpp3Dom parent, String childName, String childValue, InputLocation location ) + private Xpp3Dom newDom( String name, String value, InputLocation location ) { - if ( StringUtils.isNotEmpty( childValue ) ) - { - parent.addChild( newDom( childName, childValue, location ) ); - } + return new Xpp3Dom( name, value, null, null, location ); } - private Xpp3Dom newDom( String name, String value, InputLocation location ) + private Xpp3Dom newDom( String name, List children, InputLocation location ) { - Xpp3Dom dom = new Xpp3Dom( name, location ); - dom.setValue( value ); - return dom; + return new Xpp3Dom( name, null, null, children, location ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java index 9c0f06de1eef..fe5772841873 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -41,6 +41,6 @@ public interface LifecycleBindingsInjector * @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}. */ - void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java index 23994aa6f36e..97209740740b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -38,6 +38,6 @@ public interface PluginConfigurationExpander * @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}. */ - void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java index 28ad59624914..ced5f4549621 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -38,6 +38,6 @@ public interface ReportConfigurationExpander * @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}. */ - void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java index e6d8898b13f9..e0d645120900 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -39,6 +39,6 @@ public interface ReportingConverter * @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}. */ - void convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + Model convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java index 2f9553b81e6a..057ebb97e3ab 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java @@ -19,26 +19,26 @@ * under the License. */ +import javax.inject.Named; +import javax.inject.Singleton; + import java.util.ArrayList; import java.util.Collections; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import javax.inject.Named; -import javax.inject.Singleton; - -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.ModelBase; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginContainer; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.Profile; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.ReportSet; +import org.apache.maven.api.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.merge.MavenModelMerger; @@ -58,22 +58,24 @@ public class DefaultProfileInjector private ProfileModelMerger merger = new ProfileModelMerger(); @Override - public void injectProfile( Model model, Profile profile, ModelBuildingRequest request, - ModelProblemCollector problems ) + public Model injectProfile( Model model, Profile profile, ModelBuildingRequest request, + ModelProblemCollector problems ) { if ( profile != null ) { - merger.mergeModelBase( model, profile ); + Model.Builder builder = Model.newBuilder( model ); + merger.mergeModelBase( builder, model, profile ); if ( profile.getBuild() != null ) { - if ( model.getBuild() == null ) - { - model.setBuild( new Build() ); - } - merger.mergeBuildBase( model.getBuild(), profile.getBuild() ); + Build.Builder bbuilder = Build.newBuilder(); + Build build = model.getBuild() != null ? model.getBuild() : Build.newInstance(); + merger.mergeBuildBase( bbuilder, build, profile.getBuild() ); + builder.build( bbuilder.build() ); } + return builder.build(); } + return model; } /** @@ -83,19 +85,20 @@ protected static class ProfileModelMerger extends MavenModelMerger { - public void mergeModelBase( ModelBase target, ModelBase source ) + public void mergeModelBase( ModelBase.Builder builder, ModelBase target, ModelBase source ) { - mergeModelBase( target, source, true, Collections.emptyMap() ); + mergeModelBase( builder, target, source, true, Collections.emptyMap() ); } - public void mergeBuildBase( BuildBase target, BuildBase source ) + public void mergeBuildBase( BuildBase.Builder builder, BuildBase target, BuildBase source ) { - mergeBuildBase( target, source, true, Collections.emptyMap() ); + mergeBuildBase( builder, target, source, true, Collections.emptyMap() ); } @Override - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, - boolean sourceDominant, Map context ) + protected void mergePluginContainer_Plugins( PluginContainer.Builder builder, + PluginContainer target, PluginContainer source, + boolean sourceDominant, Map context ) { List src = source.getPlugins(); if ( !src.isEmpty() ) @@ -117,8 +120,8 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta Plugin existing = master.get( key ); if ( existing != null ) { - mergePlugin( existing, element, sourceDominant, context ); - + existing = mergePlugin( existing, element, sourceDominant, context ); + master.put( key, existing ); if ( !pending.isEmpty() ) { predecessors.put( key, pending ); @@ -143,13 +146,13 @@ protected void mergePluginContainer_Plugins( PluginContainer target, PluginConta } result.addAll( pending ); - target.setPlugins( result ); + builder.plugins( result ); } } @Override - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) + protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Plugin source, + boolean sourceDominant, Map context ) { List src = source.getExecutions(); if ( !src.isEmpty() ) @@ -170,21 +173,18 @@ protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sou PluginExecution existing = merged.get( key ); if ( existing != null ) { - mergePluginExecution( existing, element, sourceDominant, context ); - } - else - { - merged.put( key, element ); + element = mergePluginExecution( existing, element, sourceDominant, context ); } + merged.put( key, element ); } - target.setExecutions( new ArrayList<>( merged.values() ) ); + builder.executions( new ArrayList<>( merged.values() ) ); } } @Override - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, - Map context ) + protected void mergeReporting_Plugins( Reporting.Builder builder, Reporting target, Reporting source, + boolean sourceDominant, Map context ) { List src = source.getPlugins(); if ( !src.isEmpty() ) @@ -203,22 +203,20 @@ protected void mergeReporting_Plugins( Reporting target, Reporting source, boole { Object key = getReportPluginKey().apply( element ); ReportPlugin existing = merged.get( key ); - if ( existing == null ) - { - merged.put( key, element ); - } - else + if ( existing != null ) { - mergeReportPlugin( existing, element, sourceDominant, context ); + element = mergeReportPlugin( existing, element, sourceDominant, context ); } + merged.put( key, element ); } - target.setPlugins( new ArrayList<>( merged.values() ) ); + builder.plugins( new ArrayList<>( merged.values() ) ); } } @Override - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, + protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, ReportPlugin target, + ReportPlugin source, boolean sourceDominant, Map context ) { List src = source.getReportSets(); @@ -239,15 +237,12 @@ protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin s ReportSet existing = merged.get( key ); if ( existing != null ) { - mergeReportSet( existing, element, sourceDominant, context ); - } - else - { - merged.put( key, element ); + element = mergeReportSet( existing, element, sourceDominant, context ); } + merged.put( key, element ); } - target.setReportSets( new ArrayList<>( merged.values() ) ); + builder.reportSets( new ArrayList<>( merged.values() ) ); } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java index 75dc10f794a8..6989a401839c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java @@ -28,8 +28,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Activation; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java index fbd7ddf02285..7103c43aea7f 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.model.Model; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -41,6 +41,6 @@ public interface ProfileInjector * @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}. */ - void injectProfile( Model model, Profile profile, ModelBuildingRequest request, ModelProblemCollector problems ); + Model injectProfile( Model model, Profile profile, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java index 53ea8d9c04d0..f91aa1a43606 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java @@ -22,7 +22,7 @@ import java.util.Collection; import java.util.List; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java index e45b8839a99f..25eda05a2eec 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java @@ -25,9 +25,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.building.ModelProblemCollector; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java index b21fd81f39e2..13566ecf6a5f 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java @@ -26,8 +26,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Activation; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java index b3b21fa15c18..33f9700a3812 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java @@ -22,9 +22,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationOS; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationOS; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.profile.ProfileActivationContext; import org.codehaus.plexus.util.Os; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java index 1779147a6581..84d78be5b0a1 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.profile.ProfileActivationContext; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java index 1668443b0599..53c67fba7681 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java @@ -22,9 +22,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationProperty; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationProperty; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java index 303aff08cff5..7ae76ad2a9ef 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/InvalidRepositoryException.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Repository; +import org.apache.maven.api.model.Repository; /** * Signals an error when adding a repository to the model resolver. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java index 146d4531f45f..5e6e321466de 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java @@ -19,9 +19,11 @@ * under the License. */ -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; +import java.util.concurrent.atomic.AtomicReference; + +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.building.ModelSource; /** @@ -64,7 +66,7 @@ ModelSource resolveModel( String groupId, String artifactId, String version ) * * @see Parent#clone() */ - ModelSource resolveModel( Parent parent ) + ModelSource resolveModel( Parent parent, AtomicReference modified ) throws UnresolvableModelException; /** @@ -85,7 +87,7 @@ ModelSource resolveModel( Parent parent ) * * @see Dependency#clone() */ - ModelSource resolveModel( Dependency dependency ) + ModelSource resolveModel( Dependency dependency, AtomicReference modified ) throws UnresolvableModelException; /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java index 8264ed737a7f..21dd64ba8617 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * WorkspaceModelResolver diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java index 31df92fad022..bb6a82025677 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/DefaultSuperPomProvider.java @@ -28,8 +28,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelProcessor; /** @@ -78,9 +78,8 @@ public Model getSuperModel( String version ) String modelId = "org.apache.maven:maven-model-builder:" + this.getClass().getPackage().getImplementationVersion() + ":super-pom"; - InputSource inputSource = new InputSource(); - inputSource.setModelId( modelId ); - inputSource.setLocation( getClass().getResource( resource ).toExternalForm() ); + InputSource inputSource = new InputSource( + modelId, getClass().getResource( resource ).toExternalForm() ); options.put( ModelProcessor.INPUT_SOURCE, inputSource ); superModel = modelProcessor.read( is, options ); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java index 3f44fb7e4e3c..cf8443a7ba73 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/superpom/SuperPomProvider.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * Provides the super POM that all models implicitly inherit from. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java index 93a99ccf3b9d..81be8cefc58b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java @@ -19,33 +19,9 @@ * under the License. */ -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.InputLocationTracker; -import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Repository; -import org.apache.maven.model.Resource; -import org.apache.maven.model.building.ModelBuildingRequest; -import org.apache.maven.model.building.ModelProblem.Severity; -import org.apache.maven.model.building.ModelProblem.Version; -import org.apache.maven.model.building.ModelProblemCollector; -import org.apache.maven.model.building.ModelProblemCollectorRequest; -import org.apache.maven.model.interpolation.ModelVersionProcessor; -import org.codehaus.plexus.util.StringUtils; +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; import java.io.File; import java.util.Arrays; @@ -58,9 +34,33 @@ import java.util.regex.Matcher; import java.util.regex.Pattern; -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.BuildBase; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.DependencyManagement; +import org.apache.maven.api.model.DistributionManagement; +import org.apache.maven.api.model.Exclusion; +import org.apache.maven.api.model.InputLocation; +import org.apache.maven.api.model.InputLocationTracker; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.PluginExecution; +import org.apache.maven.api.model.PluginManagement; +import org.apache.maven.api.model.Profile; +import org.apache.maven.api.model.ReportPlugin; +import org.apache.maven.api.model.Reporting; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.model.Resource; +import org.apache.maven.model.building.ModelBuildingRequest; +import org.apache.maven.model.building.ModelProblem.Severity; +import org.apache.maven.model.building.ModelProblem.Version; +import org.apache.maven.model.building.ModelProblemCollector; +import org.apache.maven.model.building.ModelProblemCollectorRequest; +import org.apache.maven.model.interpolation.ModelVersionProcessor; +import org.codehaus.plexus.util.StringUtils; /** * @author Trygve Laugstøl diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java b/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java index 198ba5ac5238..f2144c2a66e1 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java index 98e2773ba96a..b86e358adff5 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java @@ -23,9 +23,9 @@ import java.io.FileInputStream; import java.nio.file.Paths; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.MavenXpp3Reader; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -60,7 +60,8 @@ public void testCompleteWiring() assertNotNull( result ); assertNotNull( result.getEffectiveModel() ); assertEquals( "activated", result.getEffectiveModel().getProperties().get( "profile.file" ) ); - Xpp3Dom conf = (Xpp3Dom) result.getEffectiveModel().getBuild().getPlugins().get( 0 ).getConfiguration(); + Dom conf = result.getEffectiveModel().getBuild().getPlugins().get( 0 ).getConfiguration(); + assertNotNull( conf ); assertEquals( "1.5", conf.getChild( "source" ).getValue() ); assertEquals( " 1.5 ", conf.getChild( "target" ).getValue() ); } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java index 767f5fb5e504..c9319e39a4a4 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java @@ -4,8 +4,9 @@ import static org.junit.jupiter.api.Assertions.assertThrows; import java.io.File; + import java.util.concurrent.atomic.AtomicReference; -/* + /* * 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 @@ -24,10 +25,10 @@ * under the License. */ -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.resolution.InvalidRepositoryException; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.UnresolvableModelException; @@ -98,7 +99,7 @@ public void testCycleInImports() static class CycleInImportsResolver extends BaseModelResolver { @Override - public ModelSource resolveModel(Dependency dependency) throws UnresolvableModelException + public ModelSource resolveModel(Dependency dependency, AtomicReference modified ) throws UnresolvableModelException { switch ( dependency.getManagementKey() ) { @@ -119,13 +120,13 @@ public ModelSource resolveModel( String groupId, String artifactId, String versi } @Override - public ModelSource resolveModel( Parent parent ) throws UnresolvableModelException + public ModelSource resolveModel( Parent parent, AtomicReference modified ) throws UnresolvableModelException { return null; } @Override - public ModelSource resolveModel( Dependency dependency ) throws UnresolvableModelException + public ModelSource resolveModel( Dependency dependency, AtomicReference modified ) throws UnresolvableModelException { return null; } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java index 286664ce14ba..b3755d9b6cb4 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.maven.model.merge.ModelMerger; +import org.apache.maven.model.v4.ModelMerger; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java index b311d771fd90..629cebd20fda 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; /** * A simple model problem collector for testing the model building components. diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java index b573ad19b1ea..a2191f0b9b8d 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/inheritance/DefaultInheritanceAssemblerTest.java @@ -23,7 +23,7 @@ import java.io.IOException; import java.nio.file.Path; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.AbstractModelSourceTransformer; import org.apache.maven.model.building.SimpleProblemCollector; import org.apache.maven.model.building.TransformerContext; @@ -211,18 +211,18 @@ public void testInheritance( String baseName, boolean fromRepo ) { // when model is read from repo, a stream is used, then pomFile == null // (has consequences in inheritance algorithm since getProjectDirectory() returns null) - parent.setPomFile( null ); - child.setPomFile( null ); + parent = Model.newBuilder( parent, true ).pomFile( null ).build(); + child = Model.newBuilder( child, true ).pomFile( null ).build(); } SimpleProblemCollector problems = new SimpleProblemCollector(); - assembler.assembleModelInheritance( child, parent, null, problems ); + Model assembled = assembler.assembleModelInheritance( child, parent, null, problems ); // write baseName + "-actual" File actual = new File( "target/test-classes/poms/inheritance/" + baseName + ( fromRepo ? "-build" : "-repo" ) + "-actual.xml" ); - writer.write( actual, null, child ); + writer.write( actual, null, assembled ); // check with getPom( baseName + "-expected" ) File expected = getPom( baseName + "-expected" ); @@ -240,11 +240,11 @@ public void testModulePathNotArtifactId() SimpleProblemCollector problems = new SimpleProblemCollector(); - assembler.assembleModelInheritance( child, parent, null, problems ); + Model model = assembler.assembleModelInheritance( child, parent, null, problems ); File actual = new File( "target/test-classes/poms/inheritance/module-path-not-artifactId-actual.xml" ); - writer.write( actual, null, child ); + writer.write( actual, null, model ); // check with getPom( "module-path-not-artifactId-effective" ) File expected = getPom( "module-path-not-artifactId-expected" ); diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java index e4a7af3fd808..988c31a14b00 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/AbstractModelInterpolatorTest.java @@ -21,20 +21,22 @@ import java.io.File; import java.text.SimpleDateFormat; +import java.util.Arrays; import java.util.Calendar; +import java.util.Collections; import java.util.Date; import java.util.Iterator; import java.util.List; import java.util.Properties; import java.util.TimeZone; -import org.apache.maven.model.Build; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Model; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Repository; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; +import org.apache.maven.api.model.Build; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Organization; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.model.Resource; +import org.apache.maven.api.model.Scm; import org.apache.maven.model.building.DefaultModelBuildingRequest; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.SimpleProblemCollector; @@ -145,12 +147,8 @@ public void testDefaultBuildTimestampFormatWithLocalTimeZoneMidnightRollover() @Test public void testShouldNotThrowExceptionOnReferenceToNonExistentValue() throws Exception { - Model model = new Model(); - - Scm scm = new Scm(); - scm.setConnection( "${test}/somepath" ); - - model.setScm( scm ); + Scm scm = Scm.newBuilder().connection( "${test}/somepath" ).build(); + Model model = Model.newBuilder().scm( scm ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -165,12 +163,8 @@ public void testShouldNotThrowExceptionOnReferenceToNonExistentValue() throws Ex @Test public void testShouldThrowExceptionOnRecursiveScmConnectionReference() throws Exception { - Model model = new Model(); - - Scm scm = new Scm(); - scm.setConnection( "${project.scm.connection}/somepath" ); - - model.setScm( scm ); + Scm scm = Scm.newBuilder().connection( "${project.scm.connection}/somepath" ).build(); + Model model = Model.newBuilder().scm( scm ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -182,14 +176,10 @@ public void testShouldThrowExceptionOnRecursiveScmConnectionReference() throws E @Test public void testShouldNotThrowExceptionOnReferenceToValueContainingNakedExpression() throws Exception { - Model model = new Model(); - - Scm scm = new Scm(); - scm.setConnection( "${test}/somepath" ); - - model.setScm( scm ); - - model.addProperty( "test", "test" ); + Scm scm = Scm.newBuilder().connection( "${test}/somepath" ).build(); + Properties props = new Properties(); + props.put( "test", "test" ); + Model model = Model.newBuilder().scm( scm ).properties( props ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -207,13 +197,9 @@ public void shouldInterpolateOrganizationNameCorrectly() throws Exception { String orgName = "MyCo"; - Model model = new Model(); - model.setName( "${project.organization.name} Tools" ); - - Organization org = new Organization(); - org.setName( orgName ); - - model.setOrganization( org ); + Model model = Model.newBuilder().name( "${project.organization.name} Tools" ) + .organization( Organization.newBuilder().name( orgName ).build() ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -226,13 +212,9 @@ public void shouldInterpolateOrganizationNameCorrectly() throws Exception @Test public void shouldInterpolateDependencyVersionToSetSameAsProjectVersion() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - - Dependency dep = new Dependency(); - dep.setVersion( "${version}" ); - - model.addDependency( dep ); + Model model = Model.newBuilder().version( "3.8.1" ) + .dependencies( Collections.singletonList( Dependency.newBuilder().version( "${version}" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -247,13 +229,9 @@ public void shouldInterpolateDependencyVersionToSetSameAsProjectVersion() throws @Test public void testShouldNotInterpolateDependencyVersionWithInvalidReference() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - - Dependency dep = new Dependency(); - dep.setVersion( "${something}" ); - - model.addDependency( dep ); + Model model = Model.newBuilder().version( "3.8.1" ) + .dependencies( Collections.singletonList( Dependency.newBuilder().version( "${something}" ).build() ) ) + .build(); /* // This is the desired behaviour, however there are too many crappy poms in the repo and an issue with the @@ -283,14 +261,10 @@ public void testShouldNotInterpolateDependencyVersionWithInvalidReference() thro @Test public void testTwoReferences() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - model.setArtifactId( "foo" ); - - Dependency dep = new Dependency(); - dep.setVersion( "${artifactId}-${version}" ); - - model.addDependency( dep ); + Model model = Model.newBuilder().version( "3.8.1" ).artifactId( "foo" ) + .dependencies( Collections.singletonList( + Dependency.newBuilder().version( "${artifactId}-${version}" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -305,15 +279,10 @@ public void testTwoReferences() throws Exception @Test public void testBasedir() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - model.setArtifactId( "foo" ); - - Repository repository = new Repository(); - - repository.setUrl( "file://localhost/${basedir}/temp-repo" ); - - model.addRepository( repository ); + Model model = Model.newBuilder().version( "3.8.1" ).artifactId( "foo" ) + .repositories( Collections.singletonList( + Repository.newBuilder().url( "file://localhost/${basedir}/temp-repo" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -327,15 +296,10 @@ public void testBasedir() throws Exception @Test public void testBaseUri() throws Exception { - Model model = new Model(); - model.setVersion( "3.8.1" ); - model.setArtifactId( "foo" ); - - Repository repository = new Repository(); - - repository.setUrl( "${project.baseUri}/temp-repo" ); - - model.addRepository( repository ); + Model model = Model.newBuilder().version( "3.8.1" ).artifactId( "foo" ) + .repositories( Collections.singletonList( + Repository.newBuilder().url( "${project.baseUri}/temp-repo" ).build() ) ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -350,16 +314,12 @@ public void testBaseUri() throws Exception public void testEnvars() throws Exception { Properties context = new Properties(); - context.put( "env.HOME", "/path/to/home" ); - Model model = new Model(); - Properties modelProperties = new Properties(); - modelProperties.setProperty( "outputDirectory", "${env.HOME}" ); - model.setProperties( modelProperties ); + Model model = Model.newBuilder().properties( modelProperties ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -374,13 +334,11 @@ public void testEnvars() throws Exception @Test public void envarExpressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception { - Model model = new Model(); Properties modelProperties = new Properties(); - modelProperties.setProperty( "outputDirectory", "${env.DOES_NOT_EXIST}" ); - model.setProperties( modelProperties ); + Model model = Model.newBuilder().properties( modelProperties ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -395,13 +353,10 @@ public void envarExpressionThatEvaluatesToNullReturnsTheLiteralString() throws E @Test public void expressionThatEvaluatesToNullReturnsTheLiteralString() throws Exception { - Model model = new Model(); - Properties modelProperties = new Properties(); - modelProperties.setProperty( "outputDirectory", "${DOES_NOT_EXIST}" ); - model.setProperties( modelProperties ); + Model model = Model.newBuilder().properties( modelProperties ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -416,22 +371,15 @@ public void expressionThatEvaluatesToNullReturnsTheLiteralString() throws Except @Test public void shouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorrectly() throws Exception { - Model model = new Model(); - - Build build = new Build(); - build.setSourceDirectory( "correct" ); - - Resource res = new Resource(); - res.setDirectory( "${project.build.sourceDirectory}" ); - - build.addResource( res ); - - Resource res2 = new Resource(); - res2.setDirectory( "${build.sourceDirectory}" ); - - build.addResource( res2 ); - - model.setBuild( build ); + Model model = Model.newBuilder() + .build( Build.newBuilder() + .sourceDirectory( "correct" ) + .resources( Arrays.asList( + Resource.newBuilder().directory( "${project.build.sourceDirectory}" ).build(), + Resource.newBuilder().directory( "${build.sourceDirectory}" ).build() + ) ) + .build() ) + .build(); ModelInterpolator interpolator = createInterpolator(); @@ -443,19 +391,18 @@ public void shouldInterpolateSourceDirectoryReferencedFromResourceDirectoryCorre List outResources = out.getBuild().getResources(); Iterator resIt = outResources.iterator(); - assertEquals( build.getSourceDirectory(), resIt.next().getDirectory() ); - assertEquals( build.getSourceDirectory(), resIt.next().getDirectory() ); + assertEquals( model.getBuild().getSourceDirectory(), resIt.next().getDirectory() ); + assertEquals( model.getBuild().getSourceDirectory(), resIt.next().getDirectory() ); } @Test public void shouldInterpolateUnprefixedBasedirExpression() throws Exception { File basedir = new File( "/test/path" ); - Model model = new Model(); - Dependency dep = new Dependency(); - dep.setSystemPath( "${basedir}/artifact.jar" ); - - model.addDependency( dep ); + Model model = Model.newBuilder() + .dependencies( Collections.singletonList( + Dependency.newBuilder().systemPath( "${basedir}/artifact.jar" ).build() + ) ).build(); ModelInterpolator interpolator = createInterpolator(); @@ -480,8 +427,7 @@ public void testRecursiveExpressionCycleNPE() throws Exception props.setProperty( "bb", "${aa}" ); DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - Model model = new Model(); - model.setProperties( props ); + Model model = Model.newBuilder().properties( props ).build(); SimpleProblemCollector collector = new SimpleProblemCollector(); ModelInterpolator interpolator = createInterpolator(); @@ -498,8 +444,7 @@ public void testRecursiveExpressionCycleBaseDir() throws Exception props.setProperty( "basedir", "${basedir}" ); DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - Model model = new Model(); - model.setProperties( props ); + Model model = Model.newBuilder().properties( props ).build(); SimpleProblemCollector collector = new SimpleProblemCollector(); ModelInterpolator interpolator = createInterpolator(); @@ -517,13 +462,10 @@ public void shouldIgnorePropertiesWithPomPrefix() throws Exception final String orgName = "MyCo"; final String expectedName = "${pom.organization.name} Tools"; - Model model = new Model(); - model.setName( expectedName ); - - Organization org = new Organization(); - org.setName( orgName ); - - model.setOrganization( org ); + Model model = Model.newBuilder() + .name( expectedName ) + .organization( Organization.newBuilder().name( orgName ).build() ) + .build(); ModelInterpolator interpolator = createInterpolator(); SimpleProblemCollector collector = new SimpleProblemCollector(); diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java deleted file mode 100644 index cc2f2970c8e4..000000000000 --- a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringSearchModelInterpolatorTest.java +++ /dev/null @@ -1,618 +0,0 @@ -package org.apache.maven.model.interpolation; - -/* - * 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. - */ - -import java.io.File; -import java.lang.reflect.Field; -import java.util.ArrayList; -import java.util.Collections; -import java.util.HashMap; -import java.util.List; -import java.util.Map; -import java.util.Properties; -import java.util.concurrent.Callable; -import java.util.concurrent.CountDownLatch; -import java.util.concurrent.Future; -import java.util.concurrent.FutureTask; - -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.InputSource; -import org.apache.maven.model.Model; -import org.apache.maven.model.building.DefaultModelBuildingRequest; -import org.apache.maven.model.building.ModelBuildingRequest; -import org.apache.maven.model.building.SimpleProblemCollector; -import org.junit.jupiter.api.Test; - -import static org.hamcrest.CoreMatchers.anyOf; -import static org.hamcrest.CoreMatchers.is; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.junit.jupiter.api.Assertions.assertEquals; -import static org.junit.jupiter.api.Assertions.assertNotNull; - -/** - * StringSearchModelInterpolatorTest - not in use - * - * @author jdcasey - * @author Benjamin Bentmann - * @deprecated replaced by StringVisitorModelInterpolator (MNG-6697) - */ -public class StringSearchModelInterpolatorTest - extends AbstractModelInterpolatorTest -{ - protected ModelInterpolator createInterpolator() - { - return new StringSearchModelInterpolator( null, null, new DefaultModelVersionProcessor() ); - } - - @Test - public void testInterpolateStringArray() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - String[] values = { "${key}", "${key2}" }; - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest(p); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( values, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", values[0] ); - assertEquals( "value2", values[1] ); - } - - private ModelBuildingRequest createModelBuildingRequest( Properties p ) - { - ModelBuildingRequest config = new DefaultModelBuildingRequest(); - config.setSystemProperties( p ); - return config; - } - - @Test - public void testInterpolateObjectWithStringArrayField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - String[] values = { "${key}", "${key2}" }; - - ObjectWithStringArrayField obj = new ObjectWithStringArrayField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", obj.values[0] ); - assertEquals( "value2", obj.values[1] ); - } - - @Test - public void testInterpolateObjectWithStringListField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - List values = new ArrayList<>(); - values.add( "${key}" ); - values.add( "${key2}" ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", obj.values.get( 0 ) ); - assertEquals( "value2", obj.values.get( 1 ) ); - } - - @Test - public void testInterpolateObjectWithStringListFieldAndOneLiteralValue() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - List values = new ArrayList<>(); - values.add( "key" ); - values.add( "${key2}" ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "key", obj.values.get( 0 ) ); - assertEquals( "value2", obj.values.get( 1 ) ); - } - - @Test - public void testInterpolateObjectWithUnmodifiableStringListField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - List values = Collections.unmodifiableList( Collections.singletonList( "${key}" ) ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "${key}", obj.values.get( 0 ) ); - } - - @Test - public void testInterpolateObjectWithStringArrayListField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - p.setProperty( "key3", "value3" ); - p.setProperty( "key4", "value4" ); - - List values = new ArrayList<>(); - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - - ObjectWithListField obj = new ObjectWithListField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", ( (String[]) obj.values.get( 0 ) )[0] ); - assertEquals( "value2", ( (String[]) obj.values.get( 0 ) )[1] ); - assertEquals( "value3", ( (String[]) obj.values.get( 1 ) )[0] ); - assertEquals( "value4", ( (String[]) obj.values.get( 1 ) )[1] ); - } - - @Test - public void testInterpolateObjectWithStringToStringMapField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - Map values = new HashMap<>(); - values.put( "key", "${key}" ); - values.put( "key2", "${key2}" ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", obj.values.get( "key" ) ); - assertEquals( "value2", obj.values.get( "key2" ) ); - } - - @Test - public void testInterpolateObjectWithStringToStringMapFieldAndOneLiteralValue() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - Map values = new HashMap<>(); - values.put( "key", "val" ); - values.put( "key2", "${key2}" ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "val", obj.values.get( "key" ) ); - assertEquals( "value2", obj.values.get( "key2" ) ); - } - - @Test - public void testInterpolateObjectWithUnmodifiableStringToStringMapField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - - Map values = Collections.unmodifiableMap( Collections.singletonMap( "key", "${key}" ) ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "${key}", obj.values.get( "key" ) ); - } - - @Test - public void testInterpolateObjectWithStringToStringArrayMapField() - { - Model model = new Model(); - - Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - p.setProperty( "key3", "value3" ); - p.setProperty( "key4", "value4" ); - - Map values = new HashMap<>(); - values.put( "key", new String[] { "${key}", "${key2}" } ); - values.put( "key2", new String[] { "${key3}", "${key4}" } ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertEquals( "value", ( (String[]) obj.values.get( "key" ) )[0] ); - assertEquals( "value2", ( (String[]) obj.values.get( "key" ) )[1] ); - assertEquals( "value3", ( (String[]) obj.values.get( "key2" ) )[0] ); - assertEquals( "value4", ( (String[]) obj.values.get( "key2" ) )[1] ); - } - - @Test - public void testInterpolateObjectWithPomFile() - throws Exception - { - Model model = new Model(); - model.setPomFile( new File( System.getProperty( "user.dir" ), "pom.xml" ) ); - File baseDir = model.getProjectDirectory(); - - Properties p = new Properties(); - - Map values = new HashMap<>(); - values.put( "key", "${project.basedir}" + File.separator + "target" ); - - ObjectWithMapField obj = new ObjectWithMapField( values ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - assertThat( baseDir.getAbsolutePath(), is( System.getProperty( "user.dir" ) ) ); - assertThat( obj.values.size(), is( 1 ) ); - assertThat( (String) obj.values.get( "key" ), is( anyOf( - is( System.getProperty( "user.dir" ) + File.separator + "target" ), - // TODO why MVN adds dot /./ in paths??? - is( System.getProperty( "user.dir" ) + File.separator + '.' + File.separator + "target" ) - ) ) ); - } - - @Test - public void testNotInterpolateObjectWithFile() - throws Exception - { - Model model = new Model(); - - File baseDir = new File( System.getProperty( "user.dir" ) ); - - Properties p = new Properties(); - - ObjectWithNotInterpolatedFile obj = new ObjectWithNotInterpolatedFile( baseDir ); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - Map, ?> cache = getCachedEntries(); - - Object objCacheItem = cache.get( Object.class ); - Object fileCacheItem = cache.get( File.class ); - - assertNotNull( objCacheItem ); - assertNotNull( fileCacheItem ); - - assertThat( readFieldsArray( objCacheItem ).length, is( 0 ) ); - assertThat( readFieldsArray( fileCacheItem ).length, is( 0 ) ); - } - - private static Object[] readFieldsArray( Object o ) throws NoSuchFieldException, IllegalAccessException - { - assertNotNull( o ); - Field field = o.getClass().getDeclaredField( "fields" ); - field.setAccessible( true ); - return (Object[]) field.get( o ); - } - - private static Map, ?> getCachedEntries() throws NoSuchFieldException, IllegalAccessException - { - Field field = StringSearchModelInterpolator.class.getDeclaredField( "CACHED_ENTRIES" ); - field.setAccessible( true ); - //noinspection unchecked - return (Map, ?>) field.get( null ); - } - - @Test - public void testNotInterpolateFile() - throws Exception - { - Model model = new Model(); - - File baseDir = new File( System.getProperty( "user.dir" ) ); - - Properties p = new Properties(); - - StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - ModelBuildingRequest config = createModelBuildingRequest( p ); - - SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( baseDir, model, new File( "." ), config, collector ); - assertProblemFree( collector ); - - Map, ?> cache = getCachedEntries(); - - Object fileCacheItem = cache.get( File.class ); - - assertNotNull( fileCacheItem ); - - assertThat( readFieldsArray( fileCacheItem ).length, is( 0 ) ); - } - - - @Test - public void testConcurrentInterpolation() - throws Exception - { - final Model model = new Model(); - - final Properties p = new Properties(); - p.setProperty( "key", "value" ); - p.setProperty( "key2", "value2" ); - p.setProperty( "key3", "value3" ); - p.setProperty( "key4", "value4" ); - p.setProperty( "key5", "value5" ); - - final StringSearchModelInterpolator interpolator = (StringSearchModelInterpolator) createInterpolator(); - - int numItems = 100; - final CountDownLatch countDownLatch = new CountDownLatch(1); - - List> futures = new ArrayList<>(); - for ( int i = 0; i < numItems; i++ ) - { - Callable future = () -> - { - final ObjectWithMixedProtection obj = getValueList(); - final ModelBuildingRequest config = createModelBuildingRequest( p ); - - countDownLatch.await(); - final SimpleProblemCollector collector = new SimpleProblemCollector(); - interpolator.interpolateObject( obj, model, new File( "." ), config, collector ); - return collector; - }; - FutureTask task = new FutureTask<>( future ); - futures.add( task ); - new Thread( task ).start(); - } - countDownLatch.countDown(); // Start all the threads - for ( Future result : futures ) - { - SimpleProblemCollector problemCollector = result.get(); // ArrayIndexOutOfBoundsException are typical indication of threading issues - assertProblemFree( problemCollector ); - } - } - - private ObjectWithMixedProtection getValueList() - { - List values = new ArrayList<>(); - - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - List values2 = new ArrayList<>(); - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - List values3 = new ArrayList<>(); - values.add( new String[] { "${key}", "${key2}" } ); - values.add( new String[] { "${key3}", "${key4}" } ); - - return new ObjectWithMixedProtection( values, values2, values3, "${key5}" ); - } - - private static final class ObjectWithStringArrayField - { - private final String[] values; - - public ObjectWithStringArrayField( String[] values ) - { - this.values = values; - } - } - - private static final class ObjectWithListField - { - private final List values; - - public ObjectWithListField( List values ) - { - this.values = values; - } - } - - private static final class ObjectWithMapField - { - private final Map values; - - public ObjectWithMapField( Map values ) - { - this.values = values; - } - } - - private static final class ObjectWithNotInterpolatedFile - { - private final File f; - - ObjectWithNotInterpolatedFile( File f ) - { - this.f = f; - } - } - - @SuppressWarnings( "unused" ) - private static final class ObjectWithMixedProtection - { - private List values1; - protected List values2; - List values3; - private String fooBar; - - private ObjectWithMixedProtection( List values1, List values2, List values3 ) - { - this.values1 = values1; - this.values2 = values2; - this.values3 = values3; - } - - private ObjectWithMixedProtection( List values1, List values2, List values3, String fooBar ) - { - this.values1 = values1; - this.values2 = values2; - this.values3 = values3; - this.fooBar = fooBar; - } - - public String getFooBar() - { - return fooBar; - } - } - - @Test - public void testFinalFieldsExcludedFromInterpolation() - { - Properties props = new Properties(); - props.setProperty( "expression", "value" ); - DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - request.setUserProperties( props ); - - SimpleProblemCollector problems = new SimpleProblemCollector(); - StringSearchModelInterpolator interpolator = - new StringSearchModelInterpolator( null, null, new DefaultModelVersionProcessor() ); - interpolator.interpolateObject( new ClassWithFinalField(), new Model(), null, request, problems ); - - assertProblemFree( problems ); - } - - static class ClassWithFinalField - { - public static final String CONSTANT = "${expression}"; - } - - @Test - public void locationTrackerShouldBeExcludedFromInterpolation() - { - Properties props = new Properties(); - props.setProperty( "expression", "value" ); - DefaultModelBuildingRequest request = new DefaultModelBuildingRequest(); - request.setUserProperties( props ); - - InputSource source = new InputSource(); - source.setLocation( "${expression}" ); - source.setModelId( "${expression}" ); - Model model = new Model(); - model.setLocation( "", new InputLocation( 1, 1, source ) ); - - SimpleProblemCollector problems = new SimpleProblemCollector(); - StringSearchModelInterpolator interpolator = - new StringSearchModelInterpolator( null, null, new DefaultModelVersionProcessor() ); - interpolator.interpolateObject( model, model, null, request, problems ); - - assertProblemFree( problems ); - assertEquals( "${expression}", source.getLocation() ); - assertEquals( "${expression}", source.getModelId() ); - } - -} diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java index 636f3fb571b8..a8d2584050ff 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/merge/MavenModelMergerTest.java @@ -22,9 +22,9 @@ import java.util.Collections; -import org.apache.maven.model.Model; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Model; +import org.apache.maven.api.model.Prerequisites; +import org.apache.maven.api.model.Profile; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertEquals; @@ -38,64 +38,66 @@ public class MavenModelMergerTest @Test public void testMergeModel_ModelVersion() { - Model parent = new Model(); - parent.setModelVersion( "4.0.0" ); - Model model = new Model(); - modelMerger.mergeModel_ModelVersion( model, parent, false, null ); - assertNull( model.getModelVersion() ); + Model parent = Model.newBuilder().modelVersion( "4.0.0" ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_ModelVersion( builder, model, parent, false, null ); + assertNull( builder.build().getModelVersion() ); - model.setModelVersion( "5.0.0" ); - modelMerger.mergeModel_ModelVersion( model, parent, false, null ); - assertEquals( "5.0.0", model.getModelVersion() ); + model = Model.newBuilder().modelVersion( "5.0.0" ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_ModelVersion( builder, model, parent, false, null ); + assertEquals( "5.0.0", builder.build().getModelVersion() ); } // ArtifactId is neither inherited nor injected @Test public void testMergeModel_ArtifactId() { - Model parent = new Model(); - parent.setArtifactId( "PARENT" ); - Model model = new Model(); - modelMerger.mergeModel_ArtifactId( model, parent, false, null ); + Model parent = Model.newBuilder().artifactId( "PARENT" ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_ArtifactId( builder, model, parent, false, null ); assertNull( model.getArtifactId() ); - model.setArtifactId( "MODEL" ); - modelMerger.mergeModel_ArtifactId( model, parent, false, null ); - assertEquals( "MODEL", model.getArtifactId() ); + model = Model.newBuilder().artifactId( "MODEL" ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_ArtifactId( builder, model, parent, false, null ); + assertEquals( "MODEL", builder.build().getArtifactId() ); } // Prerequisites are neither inherited nor injected @Test public void testMergeModel_Prerequisites() { - Model parent = new Model(); - parent.setPrerequisites( new Prerequisites() ); - Model model = new Model(); - modelMerger.mergeModel_Prerequisites( model, parent, false, null ); - assertNull( model.getPrerequisites() ); + Model parent = Model.newBuilder().prerequisites( Prerequisites.newInstance() ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_Prerequisites( builder, model, parent, false, null ); + assertNull( builder.build().getPrerequisites() ); - Prerequisites modelPrerequisites = new Prerequisites(); - modelPrerequisites.setMaven( "3.0" ); - model.setPrerequisites( modelPrerequisites ); - modelMerger.mergeModel_Prerequisites( model, parent, false, null ); - assertEquals( modelPrerequisites, model.getPrerequisites() ); + Prerequisites modelPrerequisites = Prerequisites.newBuilder().maven( "3.0" ).build(); + model = Model.newBuilder().prerequisites( modelPrerequisites ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_Prerequisites( builder, model, parent, false, null ); + assertEquals( modelPrerequisites, builder.build().getPrerequisites() ); } // Profiles are neither inherited nor injected @Test public void testMergeModel_Profiles() { - Model parent = new Model(); - parent.setProfiles( Collections.singletonList( new Profile() ) );; - Model model = new Model(); - modelMerger.mergeModel_Profiles( model, parent, false, null ); - assertEquals( 0, model.getProfiles().size() ); + Model parent = Model.newBuilder().profiles( Collections.singletonList( Profile.newInstance() ) ).build(); + Model model = Model.newInstance(); + Model.Builder builder = Model.newBuilder( model ); + modelMerger.mergeModel_Profiles( builder, model, parent, false, null ); + assertEquals( 0, builder.build().getProfiles().size() ); - Profile modelProfile = new Profile(); - modelProfile.setId( "MODEL" ); - model.setProfiles( Collections.singletonList( modelProfile ) ); - modelMerger.mergeModel_Prerequisites( model, parent, false, null ); - assertEquals( Collections.singletonList( modelProfile ), model.getProfiles() ); + Profile modelProfile = Profile.newBuilder().id( "MODEL" ).build(); + model = Model.newBuilder().profiles( Collections.singletonList( modelProfile ) ).build(); + builder = Model.newBuilder( model ); + modelMerger.mergeModel_Prerequisites( builder, model, parent, false, null ); + assertEquals( Collections.singletonList( modelProfile ), builder.build().getProfiles() ); } } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java index 6140fc511f40..40fd611d6a19 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java @@ -21,7 +21,7 @@ import java.util.Properties; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.building.SimpleProblemCollector; import org.apache.maven.model.profile.DefaultProfileActivationContext; import org.apache.maven.model.profile.ProfileActivationContext; diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java index 300fc1353934..f7edf1fc35e7 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/FileProfileActivatorTest.java @@ -19,9 +19,9 @@ * under the License. */ -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationFile; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationFile; +import org.apache.maven.api.model.Profile; import org.apache.maven.model.path.DefaultPathTranslator; import org.apache.maven.model.path.ProfileActivationFilePathInterpolator; import org.apache.maven.model.profile.DefaultProfileActivationContext; @@ -100,26 +100,22 @@ public void testIsActiveExistsLeavesFileUnchanged() private Profile newExistsProfile( String filePath ) { - ActivationFile activationFile = new ActivationFile(); - activationFile.setExists( filePath ); + ActivationFile activationFile = ActivationFile.newBuilder() + .exists( filePath ).build(); return newProfile( activationFile ); } private Profile newMissingProfile( String filePath ) { - ActivationFile activationFile = new ActivationFile(); - activationFile.setMissing( filePath ); + ActivationFile activationFile = ActivationFile.newBuilder() + .missing( filePath ).build(); return newProfile( activationFile ); } private Profile newProfile( ActivationFile activationFile ) { - Activation activation = new Activation(); - activation.setFile( activationFile ); - - Profile profile = new Profile(); - profile.setActivation( activation ); - - return profile; + Activation activation = Activation.newBuilder() + .file( activationFile ).build(); + return Profile.newBuilder().activation( activation ).build(); } } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java index ce57bf0dad99..dbfb4749416c 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivatorTest.java @@ -21,8 +21,8 @@ import java.util.Properties; -import org.apache.maven.model.Activation; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.Profile; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -44,11 +44,9 @@ void setUp() throws Exception private Profile newProfile(String jdkVersion ) { - Activation a = new Activation(); - a.setJdk( jdkVersion ); + Activation a = Activation.newBuilder().jdk( jdkVersion ).build(); - Profile p = new Profile(); - p.setActivation( a ); + Profile p = Profile.newBuilder().activation( a ).build(); return p; } @@ -64,11 +62,11 @@ private Properties newProperties( String javaVersion ) public void testNullSafe() throws Exception { - Profile p = new Profile(); + Profile p = Profile.newInstance(); assertActivation( false, p, newContext( null, null ) ); - p.setActivation( new Activation() ); + p = p.withActivation( Activation.newInstance() ); assertActivation( false, p, newContext( null, null ) ); } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java index 72a6775623b5..2114dc5ac7c4 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/PropertyProfileActivatorTest.java @@ -21,9 +21,9 @@ import java.util.Properties; -import org.apache.maven.model.Activation; -import org.apache.maven.model.ActivationProperty; -import org.apache.maven.model.Profile; +import org.apache.maven.api.model.Activation; +import org.apache.maven.api.model.ActivationProperty; +import org.apache.maven.api.model.Profile; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; @@ -45,15 +45,14 @@ void setUp() throws Exception private Profile newProfile(String key, String value ) { - ActivationProperty ap = new ActivationProperty(); - ap.setName( key ); - ap.setValue( value ); + ActivationProperty ap = ActivationProperty.newBuilder() + .name( key ) + .value( value ) + .build(); - Activation a = new Activation(); - a.setProperty( ap ); + Activation a = Activation.newBuilder().property( ap ).build(); - Profile p = new Profile(); - p.setActivation( a ); + Profile p = Profile.newBuilder().activation( a ).build(); return p; } @@ -69,11 +68,11 @@ private Properties newProperties( String key, String value ) public void testNullSafe() throws Exception { - Profile p = new Profile(); + Profile p = Profile.newInstance(); assertActivation( false, p, newContext( null, null ) ); - p.setActivation( new Activation() ); + p = p.withActivation( Activation.newInstance() ); assertActivation( false, p, newContext( null, null ) ); } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java index 57dae7ccbe0d..7510d8b1169a 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java @@ -22,12 +22,12 @@ import java.io.InputStream; import java.util.List; -import org.apache.maven.model.Model; +import org.apache.maven.api.model.Model; import org.apache.maven.model.building.DefaultModelBuildingRequest; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.SimpleProblemCollector; import org.apache.maven.model.interpolation.DefaultModelVersionProcessor; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.apache.maven.model.v4.MavenXpp3Reader; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/maven-model/pom.xml b/maven-model/pom.xml index 83f4bf54ecf1..e4e4b5d312e7 100644 --- a/maven-model/pom.xml +++ b/maven-model/pom.xml @@ -35,8 +35,14 @@ under the License. - org.codehaus.plexus - plexus-utils + org.apache.maven + maven-api-model + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT org.hamcrest @@ -48,27 +54,69 @@ under the License. - org.codehaus.modello - modello-maven-plugin - - 4.0.0 - - src/main/mdo/maven.mdo - - + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy-model + generate-sources + + copy + + + + + org.apache.maven + maven-api-model + 4.0.0-alpha-1-SNAPSHOT + mdo + target/mdo/ + maven.mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT - modello + velocity + generate-sources - java - xpp3-reader - xpp3-extended-reader - xpp3-writer - xpp3-extended-writer + velocity + + 4.0.0 + + target/mdo/maven.mdo + + + + + + + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + diff --git a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java new file mode 100644 index 000000000000..c4bca7817489 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java @@ -0,0 +1,428 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.util.stream.Collectors; + +/** + * Class InputLocation. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings( "all" ) +public final class InputLocation + implements java.io.Serializable, Cloneable, InputLocationTracker +{ + + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * The one-based line number. The value will be non-positive if + * unknown. + */ + private int lineNumber = -1; + + /** + * The one-based column number. The value will be non-positive + * if unknown. + */ + private int columnNumber = -1; + + /** + * Field source. + */ + private InputSource source; + + /** + * Field locations. + */ + private java.util.Map locations; + + /** + * Field location. + */ + private InputLocation location; + + + //----------------/ + //- Constructors -/ + //----------------/ + + public InputLocation( org.apache.maven.api.model.InputLocation location ) + { + this.lineNumber = location.getLineNumber(); + this.columnNumber = location.getColumnNumber(); + this.source = location.getSource() != null ? new InputSource( location.getSource() ) : null; + this.locations = location.getLocations().isEmpty() ? null + : location.getLocations().entrySet().stream().collect( + Collectors.toMap( e -> e.getKey(), e -> new InputLocation( e.getValue() ) ) ); + } + + public InputLocation( int lineNumber, int columnNumber) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + } //-- org.apache.maven.model.InputLocation(int, int) + + public InputLocation(int lineNumber, int columnNumber, InputSource source) + { + this.lineNumber = lineNumber; + this.columnNumber = columnNumber; + this.source = source; + } //-- org.apache.maven.model.InputLocation(int, int, InputSource) + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method clone. + * + * @return InputLocation + */ + public InputLocation clone() + { + try + { + InputLocation copy = (InputLocation) super.clone(); + + if ( copy.locations != null ) + { + copy.locations = new java.util.LinkedHashMap( copy.locations ); + } + + return copy; + } + catch ( Exception ex ) + { + throw (RuntimeException) new UnsupportedOperationException( getClass().getName() + + " does not support clone()" ).initCause( ex ); + } + } //-- InputLocation clone() + + /** + * Get the one-based column number. The value will be + * non-positive if unknown. + * + * @return int + */ + public int getColumnNumber() + { + return this.columnNumber; + } //-- int getColumnNumber() + + /** + * Get the one-based line number. The value will be + * non-positive if unknown. + * + * @return int + */ + public int getLineNumber() + { + return this.lineNumber; + } //-- int getLineNumber() + + /** + * + * + * @param key + * @return InputLocation + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + case "" : + { + return this.location; + } + default : + { + return getOtherLocation( key ); + } + } + } + else + { + return getOtherLocation( key ); + } + } //-- InputLocation getLocation( Object ) + + /** + * + * + * @return Map + */ + public java.util.Map getLocations() + { + return locations; + } //-- java.util.Map getLocations() + + /** + * + * + * @param key + * @param location + */ + public void setLocation( Object key, InputLocation location ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + case "" : + { + this.location = location; + return; + } + default : + { + setOtherLocation( key, location ); + return; + } + } + } + else + { + setOtherLocation( key, location ); + } + } //-- void setLocation( Object, InputLocation ) + + /** + * + * + * @param key + * @param location + */ + public void setOtherLocation( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new java.util.LinkedHashMap(); + } + this.locations.put( key, location ); + } + } //-- void setOtherLocation( Object, InputLocation ) + + /** + * + * + * @param key + * @return InputLocation + */ + private InputLocation getOtherLocation( Object key ) + { + return ( locations != null ) ? locations.get( key ) : null; + } //-- InputLocation getOtherLocation( Object ) + + /** + * Get the source field. + * + * @return InputSource + */ + public InputSource getSource() + { + return this.source; + } //-- InputSource getSource() + + /** + * Method merge. + * + * @param target + * @param sourceDominant + * @param source + * @return InputLocation + */ + public static InputLocation merge( InputLocation target, InputLocation source, boolean sourceDominant ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + InputLocation result = + new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource() ); + + java.util.Map locations; + java.util.Map sourceLocations = source.getLocations(); + java.util.Map targetLocations = target.getLocations(); + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new java.util.LinkedHashMap(); + locations.putAll( sourceDominant ? targetLocations : sourceLocations ); + locations.putAll( sourceDominant ? sourceLocations : targetLocations ); + } + result.setLocations( locations ); + + return result; + } //-- InputLocation merge( InputLocation, InputLocation, boolean ) + + /** + * Method merge. + * + * @param target + * @param indices + * @param source + * @return InputLocation + */ + public static InputLocation merge( InputLocation target, InputLocation source, java.util.Collection indices ) + { + if ( source == null ) + { + return target; + } + else if ( target == null ) + { + return source; + } + + InputLocation result = + new InputLocation( target.getLineNumber(), target.getColumnNumber(), target.getSource() ); + + java.util.Map locations; + java.util.Map sourceLocations = source.getLocations(); + java.util.Map targetLocations = target.getLocations(); + if ( sourceLocations == null ) + { + locations = targetLocations; + } + else if ( targetLocations == null ) + { + locations = sourceLocations; + } + else + { + locations = new java.util.LinkedHashMap(); + for ( java.util.Iterator it = indices.iterator(); it.hasNext(); ) + { + InputLocation location; + Integer index = it.next(); + if ( index.intValue() < 0 ) + { + location = sourceLocations.get( Integer.valueOf( ~index.intValue() ) ); + } + else + { + location = targetLocations.get( index ); + } + locations.put( Integer.valueOf( locations.size() ), location ); + } + } + result.setLocations( locations ); + + return result; + } //-- InputLocation merge( InputLocation, InputLocation, java.util.Collection ) + + /** + * + * + * @param locations + */ + public void setLocations( java.util.Map locations ) + { + this.locations = locations; + } //-- void setLocations( java.util.Map ) + + + public org.apache.maven.api.model.InputLocation toApiLocation() + { + if ( locations != null && locations.values().contains( this ) ) + { + if ( locations.size() == 1 && locations.values().iterator().next() == this ) + { + return new org.apache.maven.api.model.InputLocation( + lineNumber, columnNumber, + source != null ? source.toApiSource() : null, + locations.keySet().iterator().next() ); + } + else + { + return new org.apache.maven.api.model.InputLocation( + lineNumber, columnNumber, + source != null ? source.toApiSource() : null ); + } + } + else + { + return new org.apache.maven.api.model.InputLocation( + lineNumber, columnNumber, + source != null ? source.toApiSource() : null, + locations != null ? locations.entrySet().stream().collect( + Collectors.toMap( e -> e.getKey(), e -> e.getValue().toApiLocation() ) ) : null + ); + } + } + + //-----------------/ + //- Inner Classes -/ + //-----------------/ + + /** + * Class StringFormatter. + * + * @version $Revision$ $Date$ + */ + public abstract static class StringFormatter + { + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method toString. + * + * @param location + * @return String + */ + public abstract String toString( InputLocation location ); + + } + + + + + @Override + public String toString() + { + return getLineNumber() + " : " + getColumnNumber() + ", " + getSource(); + } + + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/InputLocationTracker.java b/maven-model/src/main/java/org/apache/maven/model/InputLocationTracker.java new file mode 100644 index 000000000000..62a69817d1f5 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/InputLocationTracker.java @@ -0,0 +1,54 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +/** + * Interface InputLocationTracker. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings( "all" ) +public interface InputLocationTracker +{ + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Gets the location of the specified field in the input + * source. + * + * @param field The key of the field, must not be + * null. + * @return The location of the field in the input source or + * null if unknown. + */ + public InputLocation getLocation( Object field ); + /** + * Sets the location of the specified field. + * + * @param field The key of the field, must not be + * null. + * @param location The location of the field, may be + * null. + */ + public void setLocation( Object field, InputLocation location ); +} diff --git a/maven-model/src/main/java/org/apache/maven/model/InputSource.java b/maven-model/src/main/java/org/apache/maven/model/InputSource.java new file mode 100644 index 000000000000..2f21c4981f9b --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/InputSource.java @@ -0,0 +1,150 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +/** + * Class InputSource. + * + * @version $Revision$ $Date$ + */ +@SuppressWarnings( "all" ) +public class InputSource + implements java.io.Serializable, Cloneable +{ + + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * + * + * The identifier of the POM in the format {@code + * ::}. + * + * + */ + private String modelId; + + /** + * + * + * The path/URL of the POM or {@code null} if + * unknown. + * + * + */ + private String location; + + + //----------------/ + //- Constructors -/ + //----------------/ + + public InputSource() + { + } + + public InputSource( org.apache.maven.api.model.InputSource source ) + { + this.modelId = source.getModelId(); + this.location = source.getLocation(); + } + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method clone. + * + * @return InputSource + */ + public InputSource clone() + { + try + { + InputSource copy = (InputSource) super.clone(); + + return copy; + } + catch ( Exception ex ) + { + throw (RuntimeException) new UnsupportedOperationException( getClass().getName() + + " does not support clone()" ).initCause( ex ); + } + } //-- InputSource clone() + + /** + * Get the path/URL of the POM or {@code null} if unknown. + * + * @return String + */ + public String getLocation() + { + return this.location; + } //-- String getLocation() + + /** + * Get the identifier of the POM in the format {@code + * ::}. + * + * @return String + */ + public String getModelId() + { + return this.modelId; + } //-- String getModelId() + + /** + * Set the path/URL of the POM or {@code null} if unknown. + * + * @param location + */ + public void setLocation( String location ) + { + this.location = location; + } //-- void setLocation( String ) + + /** + * Set the identifier of the POM in the format {@code + * ::}. + * + * @param modelId + */ + public void setModelId( String modelId ) + { + this.modelId = modelId; + } //-- void setModelId( String ) + + + + @Override + public String toString() + { + return getModelId() + " " + getLocation(); + } + + public org.apache.maven.api.model.InputSource toApiSource() + { + return new org.apache.maven.api.model.InputSource( modelId, location ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/MappingList.java b/maven-model/src/main/java/org/apache/maven/model/MappingList.java new file mode 100644 index 000000000000..8f64c6bdc41b --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/MappingList.java @@ -0,0 +1,75 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.List; +import java.util.function.Function; + +class MappingList extends AbstractList +{ + private final List list; + private final Function mapper; + private final Function revMapper; + + MappingList( List list, Function mapper, Function revMapper ) + { + this.list = list; + this.mapper = mapper; + this.revMapper = revMapper; + } + + @Override + public T get( int index ) + { + return mapper.apply( list.get( index ) ); + } + + @Override + public int size() + { + return list.size(); + } + + @Override + public boolean add( T t ) + { + return list.add( revMapper.apply( t ) ); + } + + @Override + public T set( int index, T element ) + { + return mapper.apply( list.set( index, revMapper.apply( element ) ) ); + } + + @Override + public void add( int index, T element ) + { + list.add( index, revMapper.apply( element ) ); + } + + @Override + public T remove( int index ) + { + return mapper.apply( list.remove( index ) ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/WrapperList.java b/maven-model/src/main/java/org/apache/maven/model/WrapperList.java new file mode 100644 index 000000000000..4d427d334576 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/WrapperList.java @@ -0,0 +1,129 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperList extends AbstractList +{ + private final Supplier> getter; + private final Consumer> setter; + private final Function mapper; + private final Function revMapper; + + WrapperList( List list, Function mapper, Function revMapper ) + { + this( () -> list, null, mapper, revMapper ); + } + + WrapperList( Supplier> getter, Consumer> setter, + Function mapper, Function revMapper ) + { + this.getter = getter; + this.setter = setter; + this.mapper = mapper; + this.revMapper = revMapper; + } + + @Override + public T get( int index ) + { + return mapper.apply( getter.get().get( index ) ); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean add( T t ) + { + Objects.requireNonNull( t ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + boolean ret = list.add( revMapper.apply( t ) ); + setter.accept( list ); + return ret; + } + else + { + return getter.get().add( revMapper.apply( t ) ); + } + } + + @Override + public T set( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.set( index, revMapper.apply( element ) ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().set( index, revMapper.apply( element ) ) ); + } + } + + @Override + public void add( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + list.add( index, revMapper.apply( element ) ); + setter.accept( list ); + } + else + { + getter.get().add( index, revMapper.apply( element ) ); + } + } + + @Override + public T remove( int index ) + { + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.remove( index ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().remove( index ) ); + } + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java b/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java new file mode 100644 index 000000000000..cffe824b73b0 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java @@ -0,0 +1,356 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperProperties extends Properties +{ + + final Supplier getter; + final Consumer setter; + + WrapperProperties( Supplier getter, Consumer setter ) + { + this.getter = getter; + this.setter = setter; + } + + @Override + public String getProperty( String key ) + { + return getter.get().getProperty( key ); + } + + @Override + public String getProperty( String key, String defaultValue ) + { + return getter.get().getProperty( key, defaultValue ); + } + + @Override + public Enumeration propertyNames() + { + return getter.get().propertyNames(); + } + + @Override + public Set stringPropertyNames() + { + return getter.get().stringPropertyNames(); + } + + @Override + public void list( PrintStream out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void list( PrintWriter out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean isEmpty() + { + return getter.get().isEmpty(); + } + + @Override + public Enumeration keys() + { + return getter.get().keys(); + } + + @Override + public Enumeration elements() + { + return getter.get().elements(); + } + + @Override + public boolean contains( Object value ) + { + return getter.get().contains( value ); + } + + @Override + public boolean containsValue( Object value ) + { + return getter.get().containsValue( value ); + } + + @Override + public boolean containsKey( Object key ) + { + return getter.get().containsKey( key ); + } + + @Override + public Object get( Object key ) + { + return getter.get().get( key ); + } + + @Override + public synchronized String toString() + { + return getter.get().toString(); + } + + @Override + public Set keySet() + { + return getter.get().keySet(); + } + + @Override + public Collection values() + { + return getter.get().values(); + } + + @Override + public Set> entrySet() + { + return getter.get().entrySet(); + } + + @Override + public synchronized boolean equals( Object o ) + { + if ( o instanceof WrapperProperties ) + { + o = ( (WrapperProperties) o ).getter.get(); + } + return getter.get().equals( o ); + } + + @Override + public synchronized int hashCode() + { + return getter.get().hashCode(); + } + + @Override + public Object getOrDefault( Object key, Object defaultValue ) + { + return getter.get().getOrDefault( key, defaultValue ); + } + + @Override + public synchronized void forEach( BiConsumer action ) + { + getter.get().forEach( action ); + } + + interface WriteOp + { + T perform( Properties props ); + } + + interface WriteOpVoid + { + void perform( Properties props ); + } + + private T writeOperation( WriteOp runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + T ret = runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + return ret; + } + + private void writeOperationVoid( WriteOpVoid runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + } + + @Override + public synchronized Object setProperty( String key, String value ) + { + return writeOperation( p -> p.setProperty( key, value ) ); + } + + @Override + public synchronized Object put( Object key, Object value ) + { + return writeOperation( p -> p.put( key, value ) ); + } + + @Override + public synchronized Object remove( Object key ) + { + return writeOperation( p -> p.remove( key ) ); + } + + @Override + public synchronized void putAll( Map t ) + { + writeOperationVoid( p -> p.putAll( t ) ); + } + + @Override + public synchronized void clear() + { + writeOperationVoid( Properties::clear ); + } + + @Override + public synchronized void replaceAll( BiFunction function ) + { + writeOperationVoid( p -> p.replaceAll( function ) ); + } + + @Override + public synchronized Object putIfAbsent( Object key, Object value ) + { + return writeOperation( p -> p.putIfAbsent( key, value ) ); + } + + @Override + public synchronized boolean remove( Object key, Object value ) + { + return writeOperation( p -> p.remove( key, value ) ); + } + + @Override + public synchronized boolean replace( Object key, Object oldValue, Object newValue ) + { + return writeOperation( p -> p.replace( key, oldValue, newValue ) ); + } + + @Override + public synchronized Object replace( Object key, Object value ) + { + return writeOperation( p -> p.replace( key, value ) ); + } + + @Override + public synchronized Object computeIfAbsent( Object key, Function mappingFunction ) + { + return writeOperation( p -> p.computeIfAbsent( key, mappingFunction ) ); + } + + @Override + public synchronized Object computeIfPresent( Object key, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.computeIfPresent( key, remappingFunction ) ); + } + + @Override + public synchronized Object compute( Object key, BiFunction remappingFunction ) + { + return writeOperation( p -> p.compute( key, remappingFunction ) ); + } + + @Override + public synchronized Object merge( Object key, Object value, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.merge( key, value, remappingFunction ) ); + } + + @Override + public synchronized void load( Reader reader ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void load( InputStream inStream ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void save( OutputStream out, String comments ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( Writer writer, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( OutputStream out, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void loadFromXML( InputStream in ) throws IOException, InvalidPropertiesFormatException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException + { + throw new UnsupportedOperationException(); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Reader.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Reader.java new file mode 100644 index 000000000000..95c8c6e70e89 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Reader.java @@ -0,0 +1,166 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import org.apache.maven.model.Model; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class MavenXpp3Reader +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public MavenXpp3Reader() + { + this( ( source, fieldName ) -> source ); + } + + public MavenXpp3Reader( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities + ? new MXParser( EntityReplacementMap.defaultEntityReplacementMap ) : new MXParser(); + parser.setInput( reader ); + return read( parser, strict ); + } //-- Model read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- Model read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- Model read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + org.apache.maven.model.v4.MavenXpp3Reader reader = contentTransformer != null + ? new org.apache.maven.model.v4.MavenXpp3Reader( contentTransformer::transform ) + : new org.apache.maven.model.v4.MavenXpp3Reader(); + reader.setAddDefaultEntities( addDefaultEntities ); + org.apache.maven.api.model.Model model = reader.read( parser, strict ); + return new Model( model ); + } //-- Model read( XmlPullParser, boolean ) + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3ReaderEx.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3ReaderEx.java new file mode 100644 index 000000000000..9fb37d0494cf --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3ReaderEx.java @@ -0,0 +1,169 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import org.apache.maven.model.InputSource; +import org.apache.maven.model.Model; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class MavenXpp3ReaderEx +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public MavenXpp3ReaderEx() + { + this( ( source, fieldName ) -> source ); + } + + public MavenXpp3ReaderEx( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities + ? new MXParser( EntityReplacementMap.defaultEntityReplacementMap ) : new MXParser( ); + parser.setInput( reader ); + return read( parser, strict, source ); + } //-- Model read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, InputSource source ) + throws IOException, XmlPullParserException + { + return read( reader, true, source ); + } //-- Model read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict, source ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, InputSource source ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), source ); + } //-- Model read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + org.apache.maven.model.v4.MavenXpp3ReaderEx reader = contentTransformer != null + ? new org.apache.maven.model.v4.MavenXpp3ReaderEx( contentTransformer::transform ) + : new org.apache.maven.model.v4.MavenXpp3ReaderEx(); + reader.setAddDefaultEntities( addDefaultEntities ); + org.apache.maven.api.model.Model model = reader.read( parser, strict, + new org.apache.maven.api.model.InputSource( source.getModelId(), source.getLocation() ) ); + return new Model( model ); + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Writer.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Writer.java new file mode 100644 index 000000000000..97e8ad41ce62 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3Writer.java @@ -0,0 +1,83 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import org.apache.maven.model.Model; + +public class MavenXpp3Writer +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( Writer writer, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3Writer xw = new org.apache.maven.model.v4.MavenXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( writer, model.getDelegate() ); + } //-- void write( Writer, Model ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( OutputStream stream, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3Writer xw = new org.apache.maven.model.v4.MavenXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( stream, model.getDelegate() ); + } //-- void write( OutputStream, Model ) + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java new file mode 100644 index 000000000000..f9ccb3b14190 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java @@ -0,0 +1,83 @@ +package org.apache.maven.model.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; +import org.apache.maven.model.Model; + +public class MavenXpp3WriterEx +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( Writer writer, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3WriterEx xw = new org.apache.maven.model.v4.MavenXpp3WriterEx(); + xw.setFileComment( fileComment ); + xw.write( writer, model.getDelegate() ); + } //-- void write( Writer, Model ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws IOException java.io.IOException if any. + */ + public void write( OutputStream stream, Model model ) + throws IOException + { + org.apache.maven.model.v4.MavenXpp3WriterEx xw = new org.apache.maven.model.v4.MavenXpp3WriterEx(); + xw.setFileComment( fileComment ); + xw.write( stream, model.getDelegate() ); + } //-- void write( OutputStream, Model ) + +} diff --git a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java b/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java deleted file mode 100644 index 2ac6fbf973a0..000000000000 --- a/maven-model/src/main/java/org/apache/maven/model/merge/ModelMerger.java +++ /dev/null @@ -1,2802 +0,0 @@ -package org.apache.maven.model.merge; - -/* - * 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. - */ - -import java.io.ObjectStreamException; -import java.util.AbstractList; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Iterator; -import java.util.LinkedHashMap; -import java.util.List; -import java.util.Map; -import java.util.Objects; -import java.util.Properties; -import java.util.function.BinaryOperator; -import java.util.function.Function; -import java.util.stream.Collectors; - -import org.apache.maven.model.Activation; -import org.apache.maven.model.Build; -import org.apache.maven.model.BuildBase; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.ConfigurationContainer; -import org.apache.maven.model.Contributor; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.DependencyManagement; -import org.apache.maven.model.DeploymentRepository; -import org.apache.maven.model.Developer; -import org.apache.maven.model.DistributionManagement; -import org.apache.maven.model.Exclusion; -import org.apache.maven.model.Extension; -import org.apache.maven.model.FileSet; -import org.apache.maven.model.InputLocation; -import org.apache.maven.model.IssueManagement; -import org.apache.maven.model.License; -import org.apache.maven.model.MailingList; -import org.apache.maven.model.Model; -import org.apache.maven.model.ModelBase; -import org.apache.maven.model.Notifier; -import org.apache.maven.model.Organization; -import org.apache.maven.model.Parent; -import org.apache.maven.model.PatternSet; -import org.apache.maven.model.Plugin; -import org.apache.maven.model.PluginConfiguration; -import org.apache.maven.model.PluginContainer; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.PluginManagement; -import org.apache.maven.model.Prerequisites; -import org.apache.maven.model.Profile; -import org.apache.maven.model.Relocation; -import org.apache.maven.model.ReportPlugin; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Reporting; -import org.apache.maven.model.Repository; -import org.apache.maven.model.RepositoryBase; -import org.apache.maven.model.RepositoryPolicy; -import org.apache.maven.model.Resource; -import org.apache.maven.model.Scm; -import org.apache.maven.model.Site; -import org.codehaus.plexus.util.xml.Xpp3Dom; - -/** - * This is a hand-crafted prototype of the default model merger that should eventually be generated by Modello by a new - * Java plugin. Code structure to merge source (read-only) object into the target object is:
    - *
  • mergeClassname( Classname target, Classname source, boolean sourceDominant, - * Map<Object, Object> context ) for each model class
  • - *
  • mergeClassname_FieldName( Classname target, Classname source, boolean - * sourceDominant, Map<Object, Object> context ) for each field of each model class
  • - *
  • Object getClassnameKey( Classname classname ) - * for each class that is used in a list
  • - *
- * Code is written like it could be generated, with default behaviour to be overridden when necessary. - * This is particularly the case for Object getClassnameKey( Classname classname ) - * method, which by default return the object itself and is expected to be overridden to calculate better suited key - * value. - * - * @author Benjamin Bentmann - */ -@SuppressWarnings( { "checkstyle:methodname" } ) -public class ModelMerger -{ - - /** - * 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 - * null. - * @param source The (read-only) source object that should be merged into the target object, may be - * null. - * @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 null. - */ - public void merge( Model target, Model source, boolean sourceDominant, Map hints ) - { - Objects.requireNonNull( target, "target cannot be null" ); - - if ( source == null ) - { - return; - } - - Map context = new HashMap<>(); - if ( hints != null ) - { - context.putAll( hints ); - } - - mergeModel( target, source, sourceDominant, context ); - } - - protected void mergeModel( Model target, Model source, boolean sourceDominant, Map context ) - { - mergeModelBase( target, source, sourceDominant, context ); - - mergeModel_ChildProjectUrlInheritAppendPath( target, source, sourceDominant, context ); - mergeModel_ModelVersion( target, source, sourceDominant, context ); - mergeModel_Parent( target, source, sourceDominant, context ); - mergeModel_GroupId( target, source, sourceDominant, context ); - mergeModel_ArtifactId( target, source, sourceDominant, context ); - mergeModel_Version( target, source, sourceDominant, context ); - mergeModel_Packaging( target, source, sourceDominant, context ); - mergeModel_Name( target, source, sourceDominant, context ); - mergeModel_Description( target, source, sourceDominant, context ); - mergeModel_Url( target, source, sourceDominant, context ); - mergeModel_InceptionYear( target, source, sourceDominant, context ); - mergeModel_Organization( target, source, sourceDominant, context ); - mergeModel_Licenses( target, source, sourceDominant, context ); - mergeModel_MailingLists( target, source, sourceDominant, context ); - mergeModel_Developers( target, source, sourceDominant, context ); - mergeModel_Contributors( target, source, sourceDominant, context ); - mergeModel_IssueManagement( target, source, sourceDominant, context ); - mergeModel_Scm( target, source, sourceDominant, context ); - mergeModel_CiManagement( target, source, sourceDominant, context ); - mergeModel_Prerequisites( target, source, sourceDominant, context ); - mergeModel_Build( target, source, sourceDominant, context ); - mergeModel_Profiles( target, source, sourceDominant, context ); - } - - protected void mergeModel_ModelVersion( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getModelVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getModelVersion() == null ) - { - target.setModelVersion( src ); - target.setLocation( "modelVersion", source.getLocation( "modelVersion" ) ); - } - } - } - - protected void mergeModel_Parent( Model target, Model source, boolean sourceDominant, Map context ) - { - Parent src = source.getParent(); - if ( src != null ) - { - Parent tgt = target.getParent(); - if ( tgt == null ) - { - tgt = new Parent(); - tgt.setRelativePath( null ); - target.setParent( tgt ); - } - mergeParent( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_GroupId( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeModel_ArtifactId( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeModel_ChildProjectUrlInheritAppendPath( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getChildProjectUrlInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildProjectUrlInheritAppendPath() == null ) - { - target.setChildProjectUrlInheritAppendPath( src ); - target.setLocation( "child.project.url.inherit.append.path", - source.getLocation( "child.project.url.inherit.append.path" ) ); - } - } - } - - protected void mergeModel_Version( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeModel_Packaging( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getPackaging(); - if ( src != null ) - { - if ( sourceDominant || target.getPackaging() == null ) - { - target.setPackaging( src ); - target.setLocation( "packaging", source.getLocation( "packaging" ) ); - } - } - } - - protected void mergeModel_Name( Model target, Model source, boolean sourceDominant, Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeModel_Description( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getDescription(); - if ( src != null ) - { - if ( sourceDominant || target.getDescription() == null ) - { - target.setDescription( src ); - target.setLocation( "description", source.getLocation( "description" ) ); - } - } - } - - protected void mergeModel_Url( Model target, Model source, boolean sourceDominant, Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeModel_InceptionYear( Model target, Model source, boolean sourceDominant, - Map context ) - { - String src = source.getInceptionYear(); - if ( src != null ) - { - if ( sourceDominant || target.getInceptionYear() == null ) - { - target.setInceptionYear( src ); - target.setLocation( "inceptionYear", source.getLocation( "inceptionYear" ) ); - } - } - } - - protected void mergeModel_Organization( Model target, Model source, boolean sourceDominant, - Map context ) - { - Organization src = source.getOrganization(); - if ( src != null ) - { - Organization tgt = target.getOrganization(); - if ( tgt == null ) - { - tgt = new Organization(); - target.setOrganization( tgt ); - } - mergeOrganization( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Licenses( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setLicenses( merge( target.getLicenses(), source.getLicenses(), - sourceDominant, getLicenseKey() ) ); - } - - protected void mergeModel_MailingLists( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setMailingLists( merge( target.getMailingLists(), source.getMailingLists(), - sourceDominant, getMailingListKey() ) ); - } - - protected void mergeModel_Developers( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setDevelopers( merge( target.getDevelopers(), source.getDevelopers(), - sourceDominant, getDeveloperKey() ) ); - } - - protected void mergeModel_Contributors( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setContributors( merge( target.getContributors(), source.getContributors(), - sourceDominant, getContributorKey() ) ); - } - - protected void mergeModel_IssueManagement( Model target, Model source, boolean sourceDominant, - Map context ) - { - IssueManagement src = source.getIssueManagement(); - if ( src != null ) - { - IssueManagement tgt = target.getIssueManagement(); - if ( tgt == null ) - { - tgt = new IssueManagement(); - target.setIssueManagement( tgt ); - } - mergeIssueManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Scm( Model target, Model source, boolean sourceDominant, Map context ) - { - Scm src = source.getScm(); - if ( src != null ) - { - Scm tgt = target.getScm(); - if ( tgt == null ) - { - tgt = new Scm(); - tgt.setTag( null ); - target.setScm( tgt ); - } - mergeScm( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_CiManagement( Model target, Model source, boolean sourceDominant, - Map context ) - { - CiManagement src = source.getCiManagement(); - if ( src != null ) - { - CiManagement tgt = target.getCiManagement(); - if ( tgt == null ) - { - tgt = new CiManagement(); - target.setCiManagement( tgt ); - } - mergeCiManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Prerequisites( Model target, Model source, boolean sourceDominant, - Map context ) - { - Prerequisites src = source.getPrerequisites(); - if ( src != null ) - { - Prerequisites tgt = target.getPrerequisites(); - if ( tgt == null ) - { - tgt = new Prerequisites(); - tgt.setMaven( null ); - target.setPrerequisites( tgt ); - } - mergePrerequisites( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Build( Model target, Model source, boolean sourceDominant, Map context ) - { - Build src = source.getBuild(); - if ( src != null ) - { - Build tgt = target.getBuild(); - if ( tgt == null ) - { - tgt = new Build(); - target.setBuild( tgt ); - } - mergeBuild( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModel_Profiles( Model target, Model source, boolean sourceDominant, - Map context ) - { - target.setProfiles( merge( target.getProfiles(), source.getProfiles(), - sourceDominant, getProfileKey() ) ); - } - - protected void mergeModelBase( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - mergeModelBase_DistributionManagement( target, source, sourceDominant, context ); - mergeModelBase_Modules( target, source, sourceDominant, context ); - mergeModelBase_Repositories( target, source, sourceDominant, context ); - mergeModelBase_PluginRepositories( target, source, sourceDominant, context ); - mergeModelBase_Dependencies( target, source, sourceDominant, context ); - mergeModelBase_Reporting( target, source, sourceDominant, context ); - mergeModelBase_DependencyManagement( target, source, sourceDominant, context ); - mergeModelBase_Properties( target, source, sourceDominant, context ); - } - - protected void mergeModelBase_Modules( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setModules( merge( target.getModules(), source.getModules(), sourceDominant, e -> e ) ); - } - - protected void mergeModelBase_Dependencies( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setDependencies( merge( target.getDependencies(), source.getDependencies(), - sourceDominant, getDependencyKey() ) ); - } - - protected void mergeModelBase_Repositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setRepositories( merge( target.getRepositories(), source.getRepositories(), - sourceDominant, getRepositoryKey() ) ); - } - - protected void mergeModelBase_PluginRepositories( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - target.setPluginRepositories( merge( target.getPluginRepositories(), source.getPluginRepositories(), - sourceDominant, getRepositoryKey() ) ); - } - - protected void mergeModelBase_DistributionManagement( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - DistributionManagement src = source.getDistributionManagement(); - if ( src != null ) - { - DistributionManagement tgt = target.getDistributionManagement(); - if ( tgt == null ) - { - tgt = new DistributionManagement(); - target.setDistributionManagement( tgt ); - } - mergeDistributionManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModelBase_Reporting( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - Reporting src = source.getReporting(); - if ( src != null ) - { - Reporting tgt = target.getReporting(); - if ( tgt == null ) - { - tgt = new Reporting(); - target.setReporting( tgt ); - } - mergeReporting( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModelBase_DependencyManagement( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - DependencyManagement src = source.getDependencyManagement(); - if ( src != null ) - { - DependencyManagement tgt = target.getDependencyManagement(); - if ( tgt == null ) - { - tgt = new DependencyManagement(); - target.setDependencyManagement( tgt ); - } - mergeDependencyManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergeModelBase_Properties( ModelBase target, ModelBase source, boolean sourceDominant, - Map context ) - { - Properties merged = new Properties(); - if ( sourceDominant ) - { - merged.putAll( target.getProperties() ); - merged.putAll( source.getProperties() ); - } - else - { - merged.putAll( source.getProperties() ); - merged.putAll( target.getProperties() ); - } - target.setProperties( merged ); - target.setLocation( "properties", InputLocation.merge( target.getLocation( "properties" ), - source.getLocation( "properties" ), sourceDominant ) ); - } - - protected void mergeDistributionManagement( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) - { - mergeDistributionManagement_Repository( target, source, sourceDominant, context ); - mergeDistributionManagement_SnapshotRepository( target, source, sourceDominant, context ); - mergeDistributionManagement_Site( target, source, sourceDominant, context ); - mergeDistributionManagement_Status( target, source, sourceDominant, context ); - mergeDistributionManagement_DownloadUrl( target, source, sourceDominant, context ); - } - - protected void mergeDistributionManagement_Repository( DistributionManagement target, - DistributionManagement source, boolean sourceDominant, - Map context ) - { - DeploymentRepository src = source.getRepository(); - if ( src != null ) - { - DeploymentRepository tgt = target.getRepository(); - if ( tgt == null ) - { - tgt = new DeploymentRepository(); - target.setRepository( tgt ); - } - mergeDeploymentRepository( tgt, src, sourceDominant, context ); - } - } - - protected void mergeDistributionManagement_SnapshotRepository( DistributionManagement target, - DistributionManagement source, - boolean sourceDominant, - Map context ) - { - DeploymentRepository src = source.getSnapshotRepository(); - if ( src != null ) - { - DeploymentRepository tgt = target.getSnapshotRepository(); - if ( tgt == null ) - { - tgt = new DeploymentRepository(); - target.setSnapshotRepository( tgt ); - } - mergeDeploymentRepository( tgt, src, sourceDominant, context ); - } - } - - protected void mergeDistributionManagement_Site( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) - { - Site src = source.getSite(); - if ( src != null ) - { - Site tgt = target.getSite(); - if ( tgt == null ) - { - tgt = new Site(); - target.setSite( tgt ); - } - mergeSite( tgt, src, sourceDominant, context ); - } - } - - protected void mergeDistributionManagement_Status( DistributionManagement target, DistributionManagement source, - boolean sourceDominant, Map context ) - { - String src = source.getStatus(); - if ( src != null ) - { - if ( sourceDominant || target.getStatus() == null ) - { - target.setStatus( src ); - target.setLocation( "status", source.getLocation( "status" ) ); - } - } - } - - protected void mergeDistributionManagement_DownloadUrl( DistributionManagement target, - DistributionManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getDownloadUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getDownloadUrl() == null ) - { - target.setDownloadUrl( src ); - target.setLocation( "downloadUrl", source.getLocation( "downloadUrl" ) ); - } - } - } - - protected void mergeRelocation( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - mergeRelocation_GroupId( target, source, sourceDominant, context ); - mergeRelocation_ArtifactId( target, source, sourceDominant, context ); - mergeRelocation_Version( target, source, sourceDominant, context ); - mergeRelocation_Message( target, source, sourceDominant, context ); - } - - protected void mergeRelocation_GroupId( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeRelocation_ArtifactId( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeRelocation_Version( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeRelocation_Message( Relocation target, Relocation source, boolean sourceDominant, - Map context ) - { - String src = source.getMessage(); - if ( src != null ) - { - if ( sourceDominant || target.getMessage() == null ) - { - target.setMessage( src ); - target.setLocation( "message", source.getLocation( "message" ) ); - } - } - } - - protected void mergeDeploymentRepository( DeploymentRepository target, DeploymentRepository source, - boolean sourceDominant, Map context ) - { - mergeRepository( target, source, sourceDominant, context ); - mergeDeploymentRepository_UniqueVersion( target, source, sourceDominant, context ); - } - - protected void mergeDeploymentRepository_UniqueVersion( DeploymentRepository target, DeploymentRepository source, - boolean sourceDominant, Map context ) - { - if ( sourceDominant ) - { - target.setUniqueVersion( source.isUniqueVersion() ); - target.setLocation( "uniqueVersion", source.getLocation( "uniqueVersion" ) ); - } - } - - protected void mergeSite( Site target, Site source, boolean sourceDominant, Map context ) - { - mergeSite_ChildSiteUrlInheritAppendPath( target, source, sourceDominant, context ); - mergeSite_Id( target, source, sourceDominant, context ); - mergeSite_Name( target, source, sourceDominant, context ); - mergeSite_Url( target, source, sourceDominant, context ); - } - - protected void mergeSite_ChildSiteUrlInheritAppendPath( Site target, Site source, boolean sourceDominant, - Map context ) - { - String src = source.getChildSiteUrlInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildSiteUrlInheritAppendPath() == null ) - { - target.setChildSiteUrlInheritAppendPath( src ); - target.setLocation( "child.site.url.inherit.append.path", - source.getLocation( "child.site.url.inherit.append.path" ) ); - } - } - } - - protected void mergeSite_Id( Site target, Site source, boolean sourceDominant, Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeSite_Name( Site target, Site source, boolean sourceDominant, Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeSite_Url( Site target, Site source, boolean sourceDominant, Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeRepository( Repository target, Repository source, boolean sourceDominant, - Map context ) - { - mergeRepositoryBase( target, source, sourceDominant, context ); - mergeRepository_Releases( target, source, sourceDominant, context ); - mergeRepository_Snapshots( target, source, sourceDominant, context ); - } - - protected void mergeRepository_Releases( Repository target, Repository source, boolean sourceDominant, - Map context ) - { - RepositoryPolicy src = source.getReleases(); - if ( src != null ) - { - RepositoryPolicy tgt = target.getReleases(); - if ( tgt == null ) - { - tgt = new RepositoryPolicy(); - target.setReleases( tgt ); - } - mergeRepositoryPolicy( tgt, src, sourceDominant, context ); - } - } - - protected void mergeRepository_Snapshots( Repository target, Repository source, boolean sourceDominant, - Map context ) - { - RepositoryPolicy src = source.getSnapshots(); - if ( src != null ) - { - RepositoryPolicy tgt = target.getSnapshots(); - if ( tgt == null ) - { - tgt = new RepositoryPolicy(); - target.setSnapshots( tgt ); - } - mergeRepositoryPolicy( tgt, src, sourceDominant, context ); - } - } - - protected void mergeRepositoryBase( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - mergeRepositoryBase_Id( target, source, sourceDominant, context ); - mergeRepositoryBase_Name( target, source, sourceDominant, context ); - mergeRepositoryBase_Url( target, source, sourceDominant, context ); - mergeRepositoryBase_Layout( target, source, sourceDominant, context ); - } - - protected void mergeRepositoryBase_Id( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeRepositoryBase_Url( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeRepositoryBase_Name( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeRepositoryBase_Layout( RepositoryBase target, RepositoryBase source, boolean sourceDominant, - Map context ) - { - String src = source.getLayout(); - if ( src != null ) - { - if ( sourceDominant || target.getLayout() == null ) - { - target.setLayout( src ); - target.setLocation( "layout", source.getLocation( "layout" ) ); - } - } - } - - protected void mergeRepositoryPolicy( RepositoryPolicy target, RepositoryPolicy source, boolean sourceDominant, - Map context ) - { - mergeRepositoryPolicy_Enabled( target, source, sourceDominant, context ); - mergeRepositoryPolicy_UpdatePolicy( target, source, sourceDominant, context ); - mergeRepositoryPolicy_ChecksumPolicy( target, source, sourceDominant, context ); - } - - protected void mergeRepositoryPolicy_Enabled( RepositoryPolicy target, RepositoryPolicy source, - boolean sourceDominant, Map context ) - { - String src = source.getEnabled(); - if ( src != null ) - { - if ( sourceDominant || target.getEnabled() == null ) - { - target.setEnabled( src ); - target.setLocation( "enabled", source.getLocation( "enabled" ) ); - } - } - } - - protected void mergeRepositoryPolicy_UpdatePolicy( RepositoryPolicy target, RepositoryPolicy source, - boolean sourceDominant, Map context ) - { - String src = source.getUpdatePolicy(); - if ( src != null ) - { - if ( sourceDominant || target.getUpdatePolicy() == null ) - { - target.setUpdatePolicy( src ); - target.setLocation( "updatePolicy", source.getLocation( "updatePolicy" ) ); - } - } - } - - protected void mergeRepositoryPolicy_ChecksumPolicy( RepositoryPolicy target, RepositoryPolicy source, - boolean sourceDominant, Map context ) - { - String src = source.getChecksumPolicy(); - if ( src != null ) - { - if ( sourceDominant || target.getChecksumPolicy() == null ) - { - target.setChecksumPolicy( src ); - target.setLocation( "checksumPolicy", source.getLocation( "checksumPolicy" ) ); - } - } - } - - protected void mergeDependency( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - mergeDependency_GroupId( target, source, sourceDominant, context ); - mergeDependency_ArtifactId( target, source, sourceDominant, context ); - mergeDependency_Version( target, source, sourceDominant, context ); - mergeDependency_Type( target, source, sourceDominant, context ); - mergeDependency_Classifier( target, source, sourceDominant, context ); - mergeDependency_Scope( target, source, sourceDominant, context ); - mergeDependency_SystemPath( target, source, sourceDominant, context ); - mergeDependency_Optional( target, source, sourceDominant, context ); - mergeDependency_Exclusions( target, source, sourceDominant, context ); - } - - protected void mergeDependency_GroupId( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeDependency_ArtifactId( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeDependency_Version( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeDependency_Type( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getType(); - if ( src != null ) - { - if ( sourceDominant || target.getType() == null ) - { - target.setType( src ); - target.setLocation( "type", source.getLocation( "type" ) ); - } - } - } - - protected void mergeDependency_Classifier( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getClassifier(); - if ( src != null ) - { - if ( sourceDominant || target.getClassifier() == null ) - { - target.setClassifier( src ); - target.setLocation( "classifier", source.getLocation( "classifier" ) ); - } - } - } - - protected void mergeDependency_Scope( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getScope(); - if ( src != null ) - { - if ( sourceDominant || target.getScope() == null ) - { - target.setScope( src ); - target.setLocation( "scope", source.getLocation( "scope" ) ); - } - } - } - - protected void mergeDependency_SystemPath( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getSystemPath(); - if ( src != null ) - { - if ( sourceDominant || target.getSystemPath() == null ) - { - target.setSystemPath( src ); - target.setLocation( "systemPath", source.getLocation( "systemPath" ) ); - } - } - } - - protected void mergeDependency_Optional( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - String src = source.getOptional(); - if ( src != null ) - { - if ( sourceDominant || target.getOptional() == null ) - { - target.setOptional( src ); - target.setLocation( "optional", source.getLocation( "optional" ) ); - } - } - } - - protected void mergeDependency_Exclusions( Dependency target, Dependency source, boolean sourceDominant, - Map context ) - { - target.setExclusions( merge( target.getExclusions(), source.getExclusions(), - sourceDominant, getExclusionKey() ) ); - } - - protected void mergeExclusion( Exclusion target, Exclusion source, boolean sourceDominant, - Map context ) - { - mergeExclusion_GroupId( target, source, sourceDominant, context ); - mergeExclusion_ArtifactId( target, source, sourceDominant, context ); - } - - protected void mergeExclusion_GroupId( Exclusion target, Exclusion source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeExclusion_ArtifactId( Exclusion target, Exclusion source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeReporting( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - mergeReporting_OutputDirectory( target, source, sourceDominant, context ); - mergeReporting_ExcludeDefaults( target, source, sourceDominant, context ); - mergeReporting_Plugins( target, source, sourceDominant, context ); - } - - protected void mergeReporting_OutputDirectory( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - String src = source.getOutputDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getOutputDirectory() == null ) - { - target.setOutputDirectory( src ); - target.setLocation( "outputDirectory", source.getLocation( "outputDirectory" ) ); - } - } - } - - protected void mergeReporting_ExcludeDefaults( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - String src = source.getExcludeDefaults(); - if ( src != null ) - { - if ( sourceDominant || target.getExcludeDefaults() == null ) - { - target.setExcludeDefaults( src ); - target.setLocation( "excludeDefaults", source.getLocation( "excludeDefaults" ) ); - } - } - } - - protected void mergeReporting_Plugins( Reporting target, Reporting source, boolean sourceDominant, - Map context ) - { - target.setPlugins( merge( target.getPlugins(), source.getPlugins(), - sourceDominant, getReportPluginKey() ) ); - } - - protected void mergeReportPlugin( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergeReportPlugin_GroupId( target, source, sourceDominant, context ); - mergeReportPlugin_ArtifactId( target, source, sourceDominant, context ); - mergeReportPlugin_Version( target, source, sourceDominant, context ); - mergeReportPlugin_ReportSets( target, source, sourceDominant, context ); - } - - protected void mergeReportPlugin_GroupId( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeReportPlugin_ArtifactId( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeReportPlugin_Version( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeReportPlugin_ReportSets( ReportPlugin target, ReportPlugin source, boolean sourceDominant, - Map context ) - { - target.setReportSets( merge( target.getReportSets(), source.getReportSets(), - sourceDominant, getReportSetKey() ) ); - } - - protected void mergeReportSet( ReportSet target, ReportSet source, boolean sourceDominant, - Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergeReportSet_Id( target, source, sourceDominant, context ); - mergeReportSet_Reports( target, source, sourceDominant, context ); - } - - protected void mergeReportSet_Id( ReportSet target, ReportSet source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeReportSet_Reports( ReportSet target, ReportSet source, boolean sourceDominant, - Map context ) - { - target.setReports( merge( target.getReports(), source.getReports(), sourceDominant, e -> e ) ); - } - - protected void mergeDependencyManagement( DependencyManagement target, DependencyManagement source, - boolean sourceDominant, Map context ) - { - mergeDependencyManagement_Dependencies( target, source, sourceDominant, context ); - } - - protected void mergeDependencyManagement_Dependencies( DependencyManagement target, DependencyManagement source, - boolean sourceDominant, Map context ) - { - target.setDependencies( merge( target.getDependencies(), source.getDependencies(), - sourceDominant, getDependencyKey() ) ); - } - - protected void mergeParent( Parent target, Parent source, boolean sourceDominant, Map context ) - { - mergeParent_GroupId( target, source, sourceDominant, context ); - mergeParent_ArtifactId( target, source, sourceDominant, context ); - mergeParent_Version( target, source, sourceDominant, context ); - mergeParent_RelativePath( target, source, sourceDominant, context ); - } - - protected void mergeParent_GroupId( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeParent_ArtifactId( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeParent_Version( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeParent_RelativePath( Parent target, Parent source, boolean sourceDominant, - Map context ) - { - String src = source.getRelativePath(); - if ( src != null ) - { - if ( sourceDominant || target.getRelativePath() == null ) - { - target.setRelativePath( src ); - target.setLocation( "relativePath", source.getLocation( "relativePath" ) ); - } - } - } - - protected void mergeOrganization( Organization target, Organization source, boolean sourceDominant, - Map context ) - { - mergeOrganization_Name( target, source, sourceDominant, context ); - mergeOrganization_Url( target, source, sourceDominant, context ); - } - - protected void mergeOrganization_Name( Organization target, Organization source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeOrganization_Url( Organization target, Organization source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeLicense( License target, License source, boolean sourceDominant, Map context ) - { - mergeLicense_Name( target, source, sourceDominant, context ); - mergeLicense_Url( target, source, sourceDominant, context ); - mergeLicense_Distribution( target, source, sourceDominant, context ); - mergeLicense_Comments( target, source, sourceDominant, context ); - } - - protected void mergeLicense_Name( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeLicense_Url( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeLicense_Distribution( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getDistribution(); - if ( src != null ) - { - if ( sourceDominant || target.getDistribution() == null ) - { - target.setDistribution( src ); - target.setLocation( "distribution", source.getLocation( "distribution" ) ); - } - } - } - - protected void mergeLicense_Comments( License target, License source, boolean sourceDominant, - Map context ) - { - String src = source.getComments(); - if ( src != null ) - { - if ( sourceDominant || target.getComments() == null ) - { - target.setComments( src ); - target.setLocation( "comments", source.getLocation( "comments" ) ); - } - } - } - - protected void mergeMailingList( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - mergeMailingList_Name( target, source, sourceDominant, context ); - mergeMailingList_Subscribe( target, source, sourceDominant, context ); - mergeMailingList_Unsubscribe( target, source, sourceDominant, context ); - mergeMailingList_Post( target, source, sourceDominant, context ); - mergeMailingList_OtherArchives( target, source, sourceDominant, context ); - } - - protected void mergeMailingList_Name( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeMailingList_Subscribe( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getSubscribe(); - if ( src != null ) - { - if ( sourceDominant || target.getSubscribe() == null ) - { - target.setSubscribe( src ); - target.setLocation( "subscribe", source.getLocation( "subscribe" ) ); - } - } - } - - protected void mergeMailingList_Unsubscribe( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getUnsubscribe(); - if ( src != null ) - { - if ( sourceDominant || target.getUnsubscribe() == null ) - { - target.setUnsubscribe( src ); - target.setLocation( "unsubscribe", source.getLocation( "unsubscribe" ) ); - } - } - } - - protected void mergeMailingList_Post( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getPost(); - if ( src != null ) - { - if ( sourceDominant || target.getPost() == null ) - { - target.setPost( src ); - target.setLocation( "post", source.getLocation( "post" ) ); - } - } - } - - protected void mergeMailingList_Archive( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - String src = source.getArchive(); - if ( src != null ) - { - if ( sourceDominant || target.getArchive() == null ) - { - target.setArchive( src ); - target.setLocation( "archive", source.getLocation( "archive" ) ); - } - } - } - - protected void mergeMailingList_OtherArchives( MailingList target, MailingList source, boolean sourceDominant, - Map context ) - { - target.setOtherArchives( merge( target.getOtherArchives(), - source.getOtherArchives(), - sourceDominant, - e -> e ) ); - } - - protected void mergeDeveloper( Developer target, Developer source, boolean sourceDominant, - Map context ) - { - mergeContributor( target, source, sourceDominant, context ); - mergeDeveloper_Id( target, source, sourceDominant, context ); - } - - protected void mergeDeveloper_Id( Developer target, Developer source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergeContributor( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - mergeContributor_Name( target, source, sourceDominant, context ); - mergeContributor_Email( target, source, sourceDominant, context ); - mergeContributor_Url( target, source, sourceDominant, context ); - mergeContributor_Organization( target, source, sourceDominant, context ); - mergeContributor_OrganizationUrl( target, source, sourceDominant, context ); - mergeContributor_Timezone( target, source, sourceDominant, context ); - mergeContributor_Roles( target, source, sourceDominant, context ); - mergeContributor_Properties( target, source, sourceDominant, context ); - } - - protected void mergeContributor_Name( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getName(); - if ( src != null ) - { - if ( sourceDominant || target.getName() == null ) - { - target.setName( src ); - target.setLocation( "name", source.getLocation( "name" ) ); - } - } - } - - protected void mergeContributor_Email( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getEmail(); - if ( src != null ) - { - if ( sourceDominant || target.getEmail() == null ) - { - target.setEmail( src ); - target.setLocation( "email", source.getLocation( "email" ) ); - } - } - } - - protected void mergeContributor_Url( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeContributor_Organization( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getOrganization(); - if ( src != null ) - { - if ( sourceDominant || target.getOrganization() == null ) - { - target.setOrganization( src ); - target.setLocation( "organization", source.getLocation( "organization" ) ); - } - } - } - - protected void mergeContributor_OrganizationUrl( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getOrganizationUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getOrganizationUrl() == null ) - { - target.setOrganizationUrl( src ); - target.setLocation( "organizationUrl", source.getLocation( "organizationUrl" ) ); - } - } - } - - protected void mergeContributor_Timezone( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - String src = source.getTimezone(); - if ( src != null ) - { - if ( sourceDominant || target.getTimezone() == null ) - { - target.setTimezone( src ); - target.setLocation( "timezone", source.getLocation( "timezone" ) ); - } - } - } - - protected void mergeContributor_Roles( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - target.setRoles( merge( target.getRoles(), source.getRoles(), sourceDominant, e -> e ) ); - } - - protected void mergeContributor_Properties( Contributor target, Contributor source, boolean sourceDominant, - Map context ) - { - Properties merged = new Properties(); - if ( sourceDominant ) - { - merged.putAll( target.getProperties() ); - merged.putAll( source.getProperties() ); - } - else - { - merged.putAll( source.getProperties() ); - merged.putAll( target.getProperties() ); - } - target.setProperties( merged ); - target.setLocation( "properties", InputLocation.merge( target.getLocation( "properties" ), - source.getLocation( "properties" ), sourceDominant ) ); - } - - protected void mergeIssueManagement( IssueManagement target, IssueManagement source, boolean sourceDominant, - Map context ) - { - mergeIssueManagement_Url( target, source, sourceDominant, context ); - mergeIssueManagement_System( target, source, sourceDominant, context ); - } - - protected void mergeIssueManagement_System( IssueManagement target, IssueManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getSystem(); - if ( src != null ) - { - if ( sourceDominant || target.getSystem() == null ) - { - target.setSystem( src ); - target.setLocation( "system", source.getLocation( "system" ) ); - } - } - } - - protected void mergeIssueManagement_Url( IssueManagement target, IssueManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeScm( Scm target, Scm source, boolean sourceDominant, Map context ) - { - mergeScm_ChildScmConnectionInheritAppendPath( target, source, sourceDominant, context ); - mergeScm_ChildScmDeveloperConnectionInheritAppendPath( target, source, sourceDominant, context ); - mergeScm_ChildScmUrlInheritAppendPath( target, source, sourceDominant, context ); - mergeScm_Url( target, source, sourceDominant, context ); - mergeScm_Connection( target, source, sourceDominant, context ); - mergeScm_DeveloperConnection( target, source, sourceDominant, context ); - mergeScm_Tag( target, source, sourceDominant, context ); - } - - protected void mergeScm_ChildScmConnectionInheritAppendPath( Scm target, Scm source, boolean sourceDominant, - Map context ) - { - String src = source.getChildScmConnectionInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildScmConnectionInheritAppendPath() == null ) - { - target.setChildScmConnectionInheritAppendPath( src ); - target.setLocation( "child.scm.connection.inherit.append.path", - source.getLocation( "child.scm.connection.inherit.append.path" ) ); - } - } - } - - protected void mergeScm_ChildScmDeveloperConnectionInheritAppendPath( Scm target, Scm source, - boolean sourceDominant, - Map context ) - { - String src = source.getChildScmDeveloperConnectionInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildScmDeveloperConnectionInheritAppendPath() == null ) - { - target.setChildScmDeveloperConnectionInheritAppendPath( src ); - target.setLocation( "child.scm.developerConnection.inherit.append.path", - source.getLocation( "child.scm.developerConnection.inherit.append.path" ) ); - } - } - } - - protected void mergeScm_ChildScmUrlInheritAppendPath( Scm target, Scm source, boolean sourceDominant, - Map context ) - { - String src = source.getChildScmUrlInheritAppendPath(); - if ( src != null ) - { - if ( sourceDominant || target.getChildScmUrlInheritAppendPath() == null ) - { - target.setChildScmUrlInheritAppendPath( src ); - target.setLocation( "child.scm.url.inherit.append.path", - source.getLocation( "child.scm.url.inherit.append.path" ) ); - } - } - } - - protected void mergeScm_Url( Scm target, Scm source, boolean sourceDominant, Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeScm_Connection( Scm target, Scm source, boolean sourceDominant, Map context ) - { - String src = source.getConnection(); - if ( src != null ) - { - if ( sourceDominant || target.getConnection() == null ) - { - target.setConnection( src ); - target.setLocation( "connection", source.getLocation( "connection" ) ); - } - } - } - - protected void mergeScm_DeveloperConnection( Scm target, Scm source, boolean sourceDominant, - Map context ) - { - String src = source.getDeveloperConnection(); - if ( src != null ) - { - if ( sourceDominant || target.getDeveloperConnection() == null ) - { - target.setDeveloperConnection( src ); - target.setLocation( "developerConnection", source.getLocation( "developerConnection" ) ); - } - } - } - - protected void mergeScm_Tag( Scm target, Scm source, boolean sourceDominant, Map context ) - { - String src = source.getTag(); - if ( src != null ) - { - if ( sourceDominant || target.getTag() == null ) - { - target.setTag( src ); - target.setLocation( "tag", source.getLocation( "tag" ) ); - } - } - } - - protected void mergeCiManagement( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - mergeCiManagement_System( target, source, sourceDominant, context ); - mergeCiManagement_Url( target, source, sourceDominant, context ); - mergeCiManagement_Notifiers( target, source, sourceDominant, context ); - } - - protected void mergeCiManagement_System( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getSystem(); - if ( src != null ) - { - if ( sourceDominant || target.getSystem() == null ) - { - target.setSystem( src ); - target.setLocation( "system", source.getLocation( "system" ) ); - } - } - } - - protected void mergeCiManagement_Url( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - String src = source.getUrl(); - if ( src != null ) - { - if ( sourceDominant || target.getUrl() == null ) - { - target.setUrl( src ); - target.setLocation( "url", source.getLocation( "url" ) ); - } - } - } - - protected void mergeCiManagement_Notifiers( CiManagement target, CiManagement source, boolean sourceDominant, - Map context ) - { - target.setNotifiers( merge( target.getNotifiers(), source.getNotifiers(), - sourceDominant, getNotifierKey() ) ); - } - - protected void mergeNotifier( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - mergeNotifier_Type( target, source, sourceDominant, context ); - mergeNotifier_Address( target, source, sourceDominant, context ); - mergeNotifier_Configuration( target, source, sourceDominant, context ); - mergeNotifier_SendOnError( target, source, sourceDominant, context ); - mergeNotifier_SendOnFailure( target, source, sourceDominant, context ); - mergeNotifier_SendOnSuccess( target, source, sourceDominant, context ); - mergeNotifier_SendOnWarning( target, source, sourceDominant, context ); - } - - protected void mergeNotifier_Type( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - String src = source.getType(); - if ( src != null ) - { - if ( sourceDominant || target.getType() == null ) - { - target.setType( src ); - } - } - } - - protected void mergeNotifier_Address( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - String src = source.getAddress(); - if ( src != null ) - { - if ( sourceDominant || target.getAddress() == null ) - { - target.setAddress( src ); - } - } - } - - protected void mergeNotifier_Configuration( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - Properties merged = new Properties(); - if ( sourceDominant ) - { - merged.putAll( target.getConfiguration() ); - merged.putAll( source.getConfiguration() ); - } - else - { - merged.putAll( source.getConfiguration() ); - merged.putAll( target.getConfiguration() ); - } - target.setConfiguration( merged ); - } - - protected void mergeNotifier_SendOnError( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnError( source.isSendOnError() ); - } - } - - protected void mergeNotifier_SendOnFailure( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnFailure( source.isSendOnFailure() ); - } - } - - protected void mergeNotifier_SendOnSuccess( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnSuccess( source.isSendOnSuccess() ); - } - } - - protected void mergeNotifier_SendOnWarning( Notifier target, Notifier source, boolean sourceDominant, - Map context ) - { - if ( sourceDominant ) - { - target.setSendOnWarning( source.isSendOnWarning() ); - } - } - - protected void mergePrerequisites( Prerequisites target, Prerequisites source, boolean sourceDominant, - Map context ) - { - mergePrerequisites_Maven( target, source, sourceDominant, context ); - } - - protected void mergePrerequisites_Maven( Prerequisites target, Prerequisites source, boolean sourceDominant, - Map context ) - { - String src = source.getMaven(); - if ( src != null ) - { - if ( sourceDominant || target.getMaven() == null ) - { - target.setMaven( src ); - target.setLocation( "maven", source.getLocation( "maven" ) ); - } - } - } - - protected void mergeBuild( Build target, Build source, boolean sourceDominant, Map context ) - { - mergeBuildBase( target, source, sourceDominant, context ); - mergeBuild_SourceDirectory( target, source, sourceDominant, context ); - mergeBuild_ScriptSourceDirectory( target, source, sourceDominant, context ); - mergeBuild_TestSourceDirectory( target, source, sourceDominant, context ); - mergeBuild_OutputDirectory( target, source, sourceDominant, context ); - mergeBuild_TestOutputDirectory( target, source, sourceDominant, context ); - mergeBuild_Extensions( target, source, sourceDominant, context ); - } - - protected void mergeBuild_SourceDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getSourceDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getSourceDirectory() == null ) - { - target.setSourceDirectory( src ); - target.setLocation( "sourceDirectory", source.getLocation( "sourceDirectory" ) ); - } - } - } - - protected void mergeBuild_ScriptSourceDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getScriptSourceDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getScriptSourceDirectory() == null ) - { - target.setScriptSourceDirectory( src ); - target.setLocation( "scriptSourceDirectory", source.getLocation( "scriptSourceDirectory" ) ); - } - } - } - - protected void mergeBuild_TestSourceDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getTestSourceDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getTestSourceDirectory() == null ) - { - target.setTestSourceDirectory( src ); - target.setLocation( "testSourceDirectory", source.getLocation( "testSourceDirectory" ) ); - } - } - } - - protected void mergeBuild_OutputDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getOutputDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getOutputDirectory() == null ) - { - target.setOutputDirectory( src ); - target.setLocation( "outputDirectory", source.getLocation( "outputDirectory" ) ); - } - } - } - - protected void mergeBuild_TestOutputDirectory( Build target, Build source, boolean sourceDominant, - Map context ) - { - String src = source.getTestOutputDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getTestOutputDirectory() == null ) - { - target.setTestOutputDirectory( src ); - target.setLocation( "testOutputDirectory", source.getLocation( "testOutputDirectory" ) ); - } - } - } - - protected void mergeBuild_Extensions( Build target, Build source, boolean sourceDominant, - Map context ) - { - target.setExtensions( merge( target.getExtensions(), source.getExtensions(), - sourceDominant, getExtensionKey() ) ); - } - - protected void mergeExtension( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - mergeExtension_GroupId( target, source, sourceDominant, context ); - mergeExtension_ArtifactId( target, source, sourceDominant, context ); - mergeExtension_Version( target, source, sourceDominant, context ); - } - - protected void mergeExtension_GroupId( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergeExtension_ArtifactId( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergeExtension_Version( Extension target, Extension source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergeBuildBase( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - mergePluginConfiguration( target, source, sourceDominant, context ); - mergeBuildBase_DefaultGoal( target, source, sourceDominant, context ); - mergeBuildBase_FinalName( target, source, sourceDominant, context ); - mergeBuildBase_Directory( target, source, sourceDominant, context ); - mergeBuildBase_Resources( target, source, sourceDominant, context ); - mergeBuildBase_TestResources( target, source, sourceDominant, context ); - mergeBuildBase_Filters( target, source, sourceDominant, context ); - } - - protected void mergeBuildBase_DefaultGoal( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - String src = source.getDefaultGoal(); - if ( src != null ) - { - if ( sourceDominant || target.getDefaultGoal() == null ) - { - target.setDefaultGoal( src ); - target.setLocation( "defaultGoal", source.getLocation( "defaultGoal" ) ); - } - } - } - - protected void mergeBuildBase_Directory( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - String src = source.getDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getDirectory() == null ) - { - target.setDirectory( src ); - target.setLocation( "directory", source.getLocation( "directory" ) ); - } - } - } - - protected void mergeBuildBase_FinalName( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - String src = source.getFinalName(); - if ( src != null ) - { - if ( sourceDominant || target.getFinalName() == null ) - { - target.setFinalName( src ); - target.setLocation( "finalName", source.getLocation( "finalName" ) ); - } - } - } - - protected void mergeBuildBase_Filters( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - target.setFilters( merge( target.getFilters(), source.getFilters(), sourceDominant, e -> e ) ); - } - - protected void mergeBuildBase_Resources( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - target.setResources( merge( target.getResources(), source.getResources(), - sourceDominant, getResourceKey() ) ); - } - - protected void mergeBuildBase_TestResources( BuildBase target, BuildBase source, boolean sourceDominant, - Map context ) - { - target.setTestResources( merge( target.getTestResources(), source.getTestResources(), - sourceDominant, getResourceKey() ) ); - } - - protected void mergePluginConfiguration( PluginConfiguration target, PluginConfiguration source, - boolean sourceDominant, Map context ) - { - mergePluginContainer( target, source, sourceDominant, context ); - mergePluginConfiguration_PluginManagement( target, source, sourceDominant, context ); - } - - protected void mergePluginConfiguration_PluginManagement( PluginConfiguration target, PluginConfiguration source, - boolean sourceDominant, Map context ) - { - PluginManagement src = source.getPluginManagement(); - if ( src != null ) - { - PluginManagement tgt = target.getPluginManagement(); - if ( tgt == null ) - { - tgt = new PluginManagement(); - target.setPluginManagement( tgt ); - } - mergePluginManagement( tgt, src, sourceDominant, context ); - } - } - - protected void mergePluginContainer( PluginContainer target, PluginContainer source, - boolean sourceDominant, Map context ) - { - mergePluginContainer_Plugins( target, source, sourceDominant, context ); - } - - protected void mergePluginContainer_Plugins( PluginContainer target, PluginContainer source, - boolean sourceDominant, Map context ) - { - target.setPlugins( merge( target.getPlugins(), source.getPlugins(), - sourceDominant, getPluginKey() ) ); - } - - protected void mergePluginManagement( PluginManagement target, PluginManagement source, boolean sourceDominant, - Map context ) - { - mergePluginContainer( target, source, sourceDominant, context ); - } - - protected void mergePlugin( Plugin target, Plugin source, boolean sourceDominant, Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergePlugin_GroupId( target, source, sourceDominant, context ); - mergePlugin_ArtifactId( target, source, sourceDominant, context ); - mergePlugin_Version( target, source, sourceDominant, context ); - mergePlugin_Extensions( target, source, sourceDominant, context ); - mergePlugin_Dependencies( target, source, sourceDominant, context ); - mergePlugin_Executions( target, source, sourceDominant, context ); - } - - protected void mergePlugin_GroupId( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getGroupId(); - if ( src != null ) - { - if ( sourceDominant || target.getGroupId() == null ) - { - target.setGroupId( src ); - target.setLocation( "groupId", source.getLocation( "groupId" ) ); - } - } - } - - protected void mergePlugin_ArtifactId( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getArtifactId(); - if ( src != null ) - { - if ( sourceDominant || target.getArtifactId() == null ) - { - target.setArtifactId( src ); - target.setLocation( "artifactId", source.getLocation( "artifactId" ) ); - } - } - } - - protected void mergePlugin_Version( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getVersion(); - if ( src != null ) - { - if ( sourceDominant || target.getVersion() == null ) - { - target.setVersion( src ); - target.setLocation( "version", source.getLocation( "version" ) ); - } - } - } - - protected void mergePlugin_Extensions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - String src = source.getExtensions(); - if ( src != null ) - { - if ( sourceDominant || target.getExtensions() == null ) - { - target.setExtensions( src ); - target.setLocation( "extensions", source.getLocation( "extensions" ) ); - } - } - } - - protected void mergePlugin_Dependencies( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - target.setDependencies( merge( target.getDependencies(), source.getDependencies(), - sourceDominant, getDependencyKey() ) ); - } - - protected void mergePlugin_Executions( Plugin target, Plugin source, boolean sourceDominant, - Map context ) - { - target.setExecutions( merge( target.getExecutions(), source.getExecutions(), - sourceDominant, getPluginExecutionKey() ) ); - } - - protected void mergeConfigurationContainer( ConfigurationContainer target, ConfigurationContainer source, - boolean sourceDominant, Map context ) - { - mergeConfigurationContainer_Inherited( target, source, sourceDominant, context ); - mergeConfigurationContainer_Configuration( target, source, sourceDominant, context ); - } - - protected void mergeConfigurationContainer_Inherited( ConfigurationContainer target, ConfigurationContainer source, - boolean sourceDominant, Map context ) - { - String src = source.getInherited(); - if ( src != null ) - { - if ( sourceDominant || target.getInherited() == null ) - { - target.setInherited( src ); - target.setLocation( "inherited", source.getLocation( "inherited" ) ); - } - } - } - - protected void mergeConfigurationContainer_Configuration( ConfigurationContainer target, - ConfigurationContainer source, boolean sourceDominant, - Map context ) - { - Xpp3Dom src = (Xpp3Dom) source.getConfiguration(); - if ( src != null ) - { - Xpp3Dom tgt = (Xpp3Dom) target.getConfiguration(); - if ( sourceDominant || tgt == null ) - { - tgt = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( src ), tgt ); - } - else - { - tgt = Xpp3Dom.mergeXpp3Dom( tgt, src ); - } - target.setConfiguration( tgt ); - } - } - - protected void mergePluginExecution( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - mergeConfigurationContainer( target, source, sourceDominant, context ); - mergePluginExecution_Id( target, source, sourceDominant, context ); - mergePluginExecution_Phase( target, source, sourceDominant, context ); - mergePluginExecution_Goals( target, source, sourceDominant, context ); - } - - protected void mergePluginExecution_Id( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - String src = source.getId(); - if ( src != null ) - { - if ( sourceDominant || target.getId() == null ) - { - target.setId( src ); - target.setLocation( "id", source.getLocation( "id" ) ); - } - } - } - - protected void mergePluginExecution_Phase( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - String src = source.getPhase(); - if ( src != null ) - { - if ( sourceDominant || target.getPhase() == null ) - { - target.setPhase( src ); - target.setLocation( "phase", source.getLocation( "phase" ) ); - } - } - } - - protected void mergePluginExecution_Goals( PluginExecution target, PluginExecution source, boolean sourceDominant, - Map context ) - { - target.setGoals( merge( target.getGoals(), source.getGoals(), sourceDominant, e -> e ) ); - } - - protected void mergeResource( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - mergeFileSet( target, source, sourceDominant, context ); - mergeResource_TargetPath( target, source, sourceDominant, context ); - mergeResource_Filtering( target, source, sourceDominant, context ); - mergeResource_MergeId( target, source, sourceDominant, context ); - } - - protected void mergeResource_TargetPath( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - String src = source.getTargetPath(); - if ( src != null ) - { - if ( sourceDominant || target.getTargetPath() == null ) - { - target.setTargetPath( src ); - target.setLocation( "targetPath", source.getLocation( "targetPath" ) ); - } - } - } - - protected void mergeResource_Filtering( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - String src = source.getFiltering(); - if ( src != null ) - { - if ( sourceDominant || target.getFiltering() == null ) - { - target.setFiltering( src ); - target.setLocation( "filtering", source.getLocation( "filtering" ) ); - } - } - } - - protected void mergeResource_MergeId( Resource target, Resource source, boolean sourceDominant, - Map context ) - { - String src = source.getMergeId(); - if ( src != null ) - { - if ( sourceDominant || target.getMergeId() == null ) - { - target.setMergeId( src ); - } - } - } - - protected void mergeFileSet( FileSet target, FileSet source, boolean sourceDominant, Map context ) - { - mergePatternSet( target, source, sourceDominant, context ); - mergeFileSet_Directory( target, source, sourceDominant, context ); - } - - protected void mergeFileSet_Directory( FileSet target, FileSet source, boolean sourceDominant, - Map context ) - { - String src = source.getDirectory(); - if ( src != null ) - { - if ( sourceDominant || target.getDirectory() == null ) - { - target.setDirectory( src ); - target.setLocation( "directory", source.getLocation( "directory" ) ); - } - } - } - - protected void mergePatternSet( PatternSet target, PatternSet source, boolean sourceDominant, - Map context ) - { - mergePatternSet_Includes( target, source, sourceDominant, context ); - mergePatternSet_Excludes( target, source, sourceDominant, context ); - } - - protected void mergePatternSet_Includes( PatternSet target, PatternSet source, boolean sourceDominant, - Map context ) - { - target.setIncludes( merge( target.getIncludes(), source.getIncludes(), sourceDominant, e -> e ) ); - } - - protected void mergePatternSet_Excludes( PatternSet target, PatternSet source, boolean sourceDominant, - Map context ) - { - target.setExcludes( merge( target.getExcludes(), source.getExcludes(), sourceDominant, e -> e ) ); - } - - protected void mergeProfile( Profile target, Profile source, boolean sourceDominant, Map context ) - { - mergeModelBase( target, source, sourceDominant, context ); - // TODO - } - - protected void mergeActivation( Activation target, Activation source, boolean sourceDominant, - Map context ) - { - // TODO - } - - @Deprecated - protected Object getDependencyKey( Dependency dependency ) - { - return dependency; - } - - @Deprecated - protected Object getPluginKey( Plugin plugin ) - { - return plugin; - } - - @Deprecated - protected Object getPluginExecutionKey( PluginExecution pluginExecution ) - { - return pluginExecution; - } - - @Deprecated - protected Object getReportPluginKey( ReportPlugin reportPlugin ) - { - return reportPlugin; - } - - @Deprecated - protected Object getReportSetKey( ReportSet reportSet ) - { - return reportSet; - } - - @Deprecated - protected Object getLicenseKey( License license ) - { - return license; - } - - @Deprecated - protected Object getMailingListKey( MailingList mailingList ) - { - return mailingList; - } - - @Deprecated - protected Object getDeveloperKey( Developer developer ) - { - return developer; - } - - @Deprecated - protected Object getContributorKey( Contributor contributor ) - { - return contributor; - } - - @Deprecated - protected Object getProfileKey( Profile profile ) - { - return profile; - } - - @Deprecated - protected Object getRepositoryKey( Repository repository ) - { - return getRepositoryBaseKey( repository ); - } - - @Deprecated - protected Object getRepositoryBaseKey( RepositoryBase repositoryBase ) - { - return repositoryBase; - } - - @Deprecated - protected Object getNotifierKey( Notifier notifier ) - { - return notifier; - } - - @Deprecated - protected Object getResourceKey( Resource resource ) - { - return resource; - } - - @Deprecated - protected Object getExtensionKey( Extension extension ) - { - return extension; - } - - @Deprecated - protected Object getExclusionKey( Exclusion exclusion ) - { - return exclusion; - } - - protected KeyComputer getDependencyKey() - { - return d -> d; - } - - protected KeyComputer getPluginKey() - { - return p -> p; - } - - protected KeyComputer getPluginExecutionKey() - { - return e -> e; - } - - protected KeyComputer getReportPluginKey() - { - return p -> p; - } - - protected KeyComputer getReportSetKey() - { - return s -> s; - } - - protected KeyComputer getLicenseKey() - { - return l -> l; - } - - protected KeyComputer getMailingListKey() - { - return l -> l; - } - - protected KeyComputer getDeveloperKey() - { - return d -> d; - } - - protected KeyComputer getContributorKey() - { - return c -> c; - } - - protected KeyComputer getProfileKey() - { - return p -> p; - } - - protected KeyComputer getRepositoryKey() - { - return r -> r; - } - - protected KeyComputer getRepositoryBaseKey() - { - return r -> r; - } - - protected KeyComputer getNotifierKey() - { - return n -> n; - } - - protected KeyComputer getResourceKey() - { - return r -> r; - } - - protected KeyComputer getExtensionKey() - { - return e -> e; - } - - protected KeyComputer getExclusionKey() - { - return e -> e; - } - - /** - * Use to compute keys for data structures - * @param the data structure type - */ - @FunctionalInterface - public interface KeyComputer extends Function - { - } - - /** - * Merge two lists - */ - private static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) - { - return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); - } - - private static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) - { - if ( src.isEmpty() ) - { - return tgt; - } - - MergingList list; - if ( tgt instanceof MergingList ) - { - list = (MergingList) tgt; - } - else - { - list = new MergingList<>( computer, src.size() + tgt.size() ); - list.mergeAll( tgt, ( t, s ) -> s ); - } - - list.mergeAll( src, remapping ); - return list; - } - - /** - * Merging list - * @param - */ - private static class MergingList extends AbstractList implements java.io.Serializable - { - - private final KeyComputer keyComputer; - private Map map; - private List list; - - MergingList( KeyComputer keyComputer, int initialCapacity ) - { - this.map = new LinkedHashMap<>( initialCapacity ); - this.keyComputer = keyComputer; - } - - Object writeReplace() throws ObjectStreamException - { - return new ArrayList<>( this ); - } - - @Override - public Iterator iterator() - { - if ( map != null ) - { - return map.values().iterator(); - } - else - { - return list.iterator(); - } - } - - void mergeAll( Collection vs, BinaryOperator remapping ) - { - if ( map == null ) - { - map = list.stream().collect( Collectors.toMap( keyComputer, - Function.identity(), - null, - LinkedHashMap::new ) ); - - list = null; - } - - if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) - { - for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) - { - Object key = e.getKey(); - V v = e.getValue(); - map.merge( key, v, remapping ); - } - } - else - { - for ( V v : vs ) - { - Object key = keyComputer.apply( v ); - - map.merge( key, v, remapping ); - } - } - } - - @Override - public boolean contains( Object o ) - { - if ( map != null ) - { - return map.containsValue( o ); - } - else - { - return list.contains( o ); - } - } - - private List asList() - { - if ( list == null ) - { - list = new ArrayList<>( map.values() ); - map = null; - } - return list; - } - - @Override - public void add( int index, V element ) - { - asList().add( index, element ); - } - - @Override - public V remove( int index ) - { - return asList().remove( index ); - } - - @Override - public V get( int index ) - { - return asList().get( index ); - } - - @Override - public int size() - { - if ( map != null ) - { - return map.size(); - } - else - { - return list.size(); - } - } - } -} diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm new file mode 100644 index 000000000000..9a9d972e9765 --- /dev/null +++ b/maven-model/src/main/mdo/merger.vm @@ -0,0 +1,354 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.model" ) +#set ( $package = "org.apache.maven.model.v4" ) +#set ( $className = "ModelMerger" ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * 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 + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @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 null. + */ + public Model merge( Model target, Model source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return mergeModel( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.allFields ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( src != null ) + { + Properties tgt = target.get${capField}(); + if ( tgt == null ) + { + builder.${field.name}( src ); + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm new file mode 100644 index 000000000000..ea6daf86ca32 --- /dev/null +++ b/maven-model/src/main/mdo/model-v3.vm @@ -0,0 +1,247 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.model" ) +#set ( $package = "${basePackage}" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end + #end + #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #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.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 + ">" ) ) + #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 +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable, Cloneable +{ + + #if ( ! $class.superClass ) + org.apache.maven.api.model.${class.name} delegate; + #end + + public ${class.name}() + { + this( org.apache.maven.api.model.${class.name}.newInstance() ); + } + + public ${class.name}( org.apache.maven.api.model.${class.name} delegate ) + { + #if ( $class.superClass ) + super( delegate ); + #else + this.delegate = delegate; + #end + } + + public ${class.name} clone() + { + return new ${class.name}( getDelegate() ); + } + + #if ( $class.superClass ) + @Override + #end + public org.apache.maven.api.model.${class.name} getDelegate() + { + #if ( $class.superClass ) + return ( org.apache.maven.api.model.${class.name} ) delegate; + #else + return delegate; + #end + } + + #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 ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList<${field.to}, org.apache.maven.api.model.${field.to}>( + getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), + ${field.to}::new, ${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( 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; + #else + return getDelegate().${pfx}${cap}(); + #end + } + + public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + { + #if ( $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() ); + #else + delegate = getDelegate().with${cap}( ${field.name} ); + #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" ) + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) + .collect( Collectors.toList() ) ); + #else + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) + .collect( Collectors.toList() ) ); + #end + } + + #end + #end + public InputLocation getLocation( Object key ) + { + org.apache.maven.api.model.InputLocation loc = getDelegate().getLocation( key ); + return loc != null ? new InputLocation( loc ) : null; + } + + public void setLocation( Object key, InputLocation location ) + { + delegate = org.apache.maven.api.model.${class.name}.newBuilder( getDelegate(), true ) + .location( key, location.toApiLocation() ).build(); + } + + public static List ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) + { + return list != null ? new MappingList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; + } + + public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List list ) + { + return list != null ? new MappingList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null; + } + + #foreach ( $cs in $class.getCodeSegments($version) ) +$cs.code + #end +} + #end +#end diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm new file mode 100644 index 000000000000..6fd161f10b45 --- /dev/null +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -0,0 +1,827 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.model" ) +#set ( $package = "org.apache.maven.model.v4" ) +#set ( $className = "MavenXpp3ReaderEx" ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashMap; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( new ContentTransformer() + { + public String transform( String source, String fieldName ) + { + return source; + } + } ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return 0; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + parser.setInput( reader ); + return read( parser, strict, source ); + } //-- Model read( Reader, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict, source ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) + public Model read( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict, source ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- Model read( XmlPullParser, boolean ) + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + ${classLcapName}.location( "", new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = unalias( parser.getName() ); + if ( !parsed.add( childName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); + } + int line = parser.getLineNumber(); + int column = parser.getColumnNumber(); + Map locations = null; + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + locations = new HashMap<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + locations.put( Integer.valueOf( locations.size() ), new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + // TODO: locations + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict, source ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + locations = new HashMap<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + locations.put( Integer.valueOf( locations.size() ), new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + ${field.name}.add( parse${field.toClass.name}( parser, strict, source ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + ${classLcapName}.location( childName, new InputLocation( line, column, source, locations ) ); + } + return ${classLcapName}.build(); + } + + #end +#end + + private String unalias( String tagName ) + { + switch ( tagName ) + { +#set( $aliases = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.allFields ) + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) + #end + #end +#end +#foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + return "${entry.value}"; +#end + default: + return tagName; + } + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm new file mode 100644 index 000000000000..f91fc866ba87 --- /dev/null +++ b/maven-model/src/main/mdo/reader.vm @@ -0,0 +1,848 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.model" ) +#set ( $package = "org.apache.maven.model.v4" ) +#set ( $className = "MavenXpp3Reader" ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( new ContentTransformer() + { + public String transform( String source, String fieldName ) + { + return source; + } + } ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return 0; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- Model read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- Model read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Model read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- Model read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) + public Model read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- Model read( XmlPullParser, boolean ) + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = unalias( parser.getName() ); + if ( !parsed.add( childName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); + } + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + return ${classLcapName}.build(); + } + + #end +#end + + private String unalias( String tagName ) + { + switch ( tagName ) + { +#set( $aliases = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.allFields ) + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) + #end + #end +#end +#foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + return "${entry.value}"; +#end + default: + return tagName; + } + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm new file mode 100644 index 000000000000..83e6c290003f --- /dev/null +++ b/maven-model/src/main/mdo/transformer.vm @@ -0,0 +1,154 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.model" ) +#set ( $package = "org.apache.maven.model.v4" ) +#set ( $className = "ModelTransformer" ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end + +@Generated +public class ${className} +{ + + private final Function transformer; + + public ${className}( Function transformer ) + { + this.transformer = transformer; + } + + /** + * Transforms the given model + */ + public Model visit( Model target ) + { + Objects.requireNonNull( target, "target cannot be null" ); + return transformModel( target ); + } + + /** + * The transformation function. + */ + protected String transform( String value ) + { + return transformer.apply( value ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + protected ${class.name} transform${class.name}( ${class.name} target ) + { + if ( target == null ) + { + return null; + } + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + #foreach ( $field in $allFields ) + transform${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target ); + #end + return builder.build(); + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void transform${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target ) + { + #if ( $field.type == "String" ) + String newVal = transform( target.get${capField}() ); + builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( transform( target.get${capField}(), this::transform ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties props = target.get${capField}(); + Properties newProps = null; + for ( Map.Entry entry : props.entrySet() ) + { + if ( entry.getKey() instanceof String && entry.getValue() instanceof String ) + { + String newVal = transform( ( String ) entry.getValue() ); + if ( newVal != null && newVal != entry.getValue() ) + { + if ( newProps == null ) + { + newProps = new Properties(); + newProps.putAll( props ); + builder.${field.name}( newProps ); + } + newProps.put( ( String ) entry.getKey(), newVal ); + } + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} newVal = transform${field.to}( target.get${capField}() ); + builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( transform( target.get${capField}(), this::transform${field.to} ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + protected List transform( List list, Function transformer ) + { + List newList = null; + for ( int i = 0; i < list.size(); i++ ) + { + T newVal = transformer.apply( list.get( i ) ); + if ( newVal != list.get( i ) ) + { + if ( newList == null ) + { + newList = new ArrayList<>( list ); + } + newList.set( i, newVal ); + } + } + return newList; + } + +} diff --git a/maven-model/src/main/mdo/writer-ex.vm b/maven-model/src/main/mdo/writer-ex.vm new file mode 100644 index 000000000000..da414d8e5858 --- /dev/null +++ b/maven-model/src/main/mdo/writer-ex.vm @@ -0,0 +1,32 @@ +#* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*# +#set ( $basePackage = "org.apache.maven.api.model" ) +#set ( $package = "org.apache.maven.model.v4" ) +#set ( $className = "MavenXpp3WriterEx" ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import org.apache.maven.api.annotations.Generated; + +@Generated +public class ${className} extends MavenXpp3Writer +{ + // TODO: handle locations +} diff --git a/maven-model/src/main/mdo/writer.vm b/maven-model/src/main/mdo/writer.vm new file mode 100644 index 000000000000..8d6c18ea7303 --- /dev/null +++ b/maven-model/src/main/mdo/writer.vm @@ -0,0 +1,304 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.model" ) +#set ( $package = "org.apache.maven.model.v4" ) +#set ( $className = "MavenXpp3Writer" ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, Model model ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( model.getModelEncoding(), null ); + writeModel( "project", model, serializer ); + serializer.endDocument(); + } //-- void write( Writer, Model ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, Model model ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, model.getModelEncoding() ); + serializer.startDocument( model.getModelEncoding(), null ); + writeModel( "project", model, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, Model ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${field.defaultValue} == "true" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + // TODO: name=${field.name} type=${field.type} + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( T t : list ) + { + writer.write( t ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} diff --git a/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java b/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java index f1aad049f848..69ebf66cb7bf 100644 --- a/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java +++ b/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java @@ -1,9 +1,5 @@ package org.apache.maven.model.merge; -import static org.hamcrest.MatcherAssert.assertThat; -import static org.hamcrest.Matchers.contains; -import static org.hamcrest.Matchers.is; - /* * Licensed to the Apache Software Foundation (ASF) under one * or more contributor license agreements. See the NOTICE file @@ -23,25 +19,18 @@ * under the License. */ -import java.io.ByteArrayOutputStream; -import java.io.ObjectOutputStream; -import java.util.ArrayList; import java.util.Arrays; -import org.apache.maven.model.Build; -import org.apache.maven.model.Contributor; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Developer; -import org.apache.maven.model.License; -import org.apache.maven.model.MailingList; -import org.apache.maven.model.Model; -import org.apache.maven.model.PatternSet; -import org.apache.maven.model.PluginExecution; -import org.apache.maven.model.Profile; -import org.apache.maven.model.ReportSet; -import org.apache.maven.model.Repository; +import org.apache.maven.api.model.Contributor; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Model; +import org.apache.maven.model.v4.ModelMerger; import org.junit.jupiter.api.Test; +import static org.hamcrest.MatcherAssert.assertThat; +import static org.hamcrest.Matchers.contains; +import static org.hamcrest.Matchers.is; + /** * ModelMerger is based on same instances, subclasses should override KeyComputer per type * @@ -55,56 +44,46 @@ public class ModelMergerTest @Test public void mergeArtifactId() { - Model target = new Model(); - target.setArtifactId( "TARGET" ); + Model target = Model.newBuilder().artifactId( "TARGET" ).build(); - Model source = new Model(); - source.setArtifactId( "SOURCE" ); + Model source = Model.newBuilder().artifactId( "SOURCE" ).build(); - modelMerger.merge( target, source, true, null ); - assertThat( target.getArtifactId(), is( "SOURCE" ) ); + Model merged = modelMerger.merge( target, source, true, null ); + assertThat( merged.getArtifactId(), is( "SOURCE" ) ); - target.setArtifactId( "TARGET" );; - modelMerger.merge( target, source, false, null ); - assertThat( target.getArtifactId(), is( "TARGET" ) ); + merged = modelMerger.merge( target, source, false, null ); + assertThat( merged.getArtifactId(), is( "TARGET" ) ); } @Test public void mergeSameContributors() { - Contributor contributor = new Contributor(); - contributor.setEmail( "contributor@maven.apache.org" ); + Contributor contributor = Contributor.newBuilder().email( "contributor@maven.apache.org" ).build(); - Model target = new Model(); - target.setContributors( Arrays.asList( contributor ) ); + Model target = Model.newBuilder().contributors( Arrays.asList( contributor ) ).build(); - Model source = new Model(); - source.setContributors( Arrays.asList( contributor ) ); + Model source = Model.newBuilder().contributors( Arrays.asList( contributor ) ).build(); - modelMerger.merge( target, source, true, null ); + Model merged = modelMerger.merge( target, source, true, null ); - assertThat( target.getContributors(), contains( contributor ) ); + assertThat( merged.getContributors(), contains( contributor ) ); } @Test public void mergeSameDependencies() { - Dependency dependency = new Dependency(); - dependency.setGroupId( "groupId" ); - dependency.setArtifactId( "artifactId" ); - dependency.setType( "type" ); + Dependency dependency = Dependency.newBuilder().groupId( "groupId" ).artifactId( "artifactId" ).type( "type" ).build(); - Model target = new Model(); - target.setDependencies( Arrays.asList( dependency ) ); + Model target = Model.newBuilder().dependencies( Arrays.asList( dependency ) ).build(); - Model source = new Model(); - source.setDependencies( Arrays.asList( dependency ) ); + Model source = Model.newBuilder().dependencies( Arrays.asList( dependency ) ).build(); - modelMerger.merge( target, source, true, null ); + Model merged = modelMerger.merge( target, source, true, null ); - assertThat( target.getDependencies(), contains( dependency ) ); + assertThat( merged.getDependencies(), contains( dependency ) ); } + /* @Test public void mergeDescription() { @@ -447,4 +426,5 @@ public void testMergedModelSerialization() throws Exception { ObjectOutputStream oos = new ObjectOutputStream(baos); oos.writeObject(target); } + */ } diff --git a/maven-plugin-api/pom.xml b/maven-plugin-api/pom.xml index be4b99399f7d..057014307c82 100644 --- a/maven-plugin-api/pom.xml +++ b/maven-plugin-api/pom.xml @@ -61,13 +61,23 @@ under the License. org.codehaus.modello modello-maven-plugin + 2.0.0 + + + modello + none + modello-site-doc pre-site @@ -82,6 +92,31 @@ under the License. + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + + velocity + generate-sources + + velocity + + + 1.0.0 + + src/main/mdo/lifecycle.mdo + + + + + + + + + + diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java index b41eba9878c6..52d1f5e6ea6f 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/MojoDescriptor.java @@ -139,6 +139,8 @@ public class MojoDescriptor */ private boolean threadSafe = false; + private boolean v4Api = false; + /** * Default constructor. */ @@ -455,7 +457,7 @@ public void setMojoConfiguration( PlexusConfiguration mojoConfiguration ) /** {@inheritDoc} */ public String getRole() { - return Mojo.ROLE; + return isV4Api() ? "org.apache.maven.api.plugin.Mojo" : Mojo.ROLE; } /** {@inheritDoc} */ @@ -656,6 +658,16 @@ public boolean isForking() || ( getExecutePhase() != null && getExecutePhase().length() > 0 ); } + public boolean isV4Api() + { + return v4Api; + } + + public void setV4Api( boolean v4Api ) + { + this.v4Api = v4Api; + } + /** * Creates a shallow copy of this mojo descriptor. */ diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java index 5747d16e9a83..a60985f1a4e2 100644 --- a/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/descriptor/PluginDescriptorBuilder.java @@ -24,12 +24,12 @@ import java.util.ArrayList; import java.util.List; +import org.apache.maven.internal.xml.XmlPlexusConfiguration; +import org.apache.maven.internal.xml.Xpp3DomBuilder; import org.codehaus.plexus.component.repository.ComponentDependency; import org.codehaus.plexus.component.repository.ComponentRequirement; import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfigurationException; -import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; -import org.codehaus.plexus.util.xml.Xpp3DomBuilder; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; /** @@ -309,6 +309,13 @@ public MojoDescriptor buildComponentDescriptor( PlexusConfiguration c, PluginDes mojo.setThreadSafe( Boolean.parseBoolean( threadSafe ) ); } + String v4Api = c.getChild( "v4Api" ).getValue(); + + if ( v4Api != null ) + { + mojo.setV4Api( Boolean.parseBoolean( v4Api ) ); + } + // ---------------------------------------------------------------------- // Configuration // ---------------------------------------------------------------------- @@ -401,7 +408,7 @@ public PlexusConfiguration buildConfiguration( Reader configuration ) { try { - return new XmlPlexusConfiguration( Xpp3DomBuilder.build( configuration ) ); + return XmlPlexusConfiguration.toPlexusConfiguration( Xpp3DomBuilder.build( configuration ) ); } catch ( IOException | XmlPullParserException e ) { diff --git a/maven-plugin-api/src/main/mdo/merger.vm b/maven-plugin-api/src/main/mdo/merger.vm new file mode 100644 index 000000000000..b29d8d5a68ad --- /dev/null +++ b/maven-plugin-api/src/main/mdo/merger.vm @@ -0,0 +1,358 @@ +#* + 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. +*# +#set ( $basePackage = "${model.getDefault('package').getValue()}" ) +#set ( $package = "${basePackage}.merge" ) +#set ( $className = "${model.name}Merger" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * 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 + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @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 null. + */ + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return merge${root.name}( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.getFields($version) ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( src != null ) + { + Properties tgt = target.get${capField}(); + if ( tgt == null ) + { + builder.${field.name}( src ); + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-plugin-api/src/main/mdo/model.vm b/maven-plugin-api/src/main/mdo/model.vm new file mode 100644 index 000000000000..2cf6778df784 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/model.vm @@ -0,0 +1,331 @@ +#* + 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. +*# +#set ( $package = "${model.getDefault('package').getValue()}" ) +# +#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.getFields($version) ) ) + #end + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end + #end + #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) + #set ( $dummy = $imports.add( "java.io.Serializable" ) ) + #set ( $dummy = $imports.add( "java.util.Collections" ) ) + #set ( $dummy = $imports.add( "java.util.HashMap" ) ) + #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "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 = $imports.add( "java.util.List" ) ) + #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #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 +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable +{ + #if ( $class == $root ) + final String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + #end + + ${class.name}( + #if ( $class == $root ) + String modelEncoding, + #end + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name${sep} + #end + ) + { + #if ( $class.superClass ) + super( + #foreach ( $field in $inheritedFields ) + #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + ${field.name}${sep} + #end + ); + #end + #if ( $class == $root ) + this.modelEncoding = modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = ${field.name}; + #end + } + + #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 ${eq}; + } + + @Override + public int hashCode() + { + return Objects.hash( ${hc} ); + } + + #end + #if ( $class == $root ) + public String getModelEncoding() + { + return modelEncoding; + } + + #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 ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + { + return this.${field.name}; + } + + #end + #foreach ( $field in $allFields ) + #set ( $cap = $Helper.capitalise( $field.name ) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + public ${class.name} with${cap}( $type $field.name ) + { + return newBuilder( this ).${field.name}( $field.name ).build(); + } + #end + + public static ${class.name} newInstance() + { + return newInstance( true ); + } + + public static ${class.name} newInstance( boolean withDefaults ) + { + return newBuilder( withDefaults ).build(); + } + + public static Builder newBuilder() + { + return newBuilder( true ); + } + + public static Builder newBuilder( boolean withDefaults ) + { + return new Builder( withDefaults ); + } + + public static Builder newBuilder( ${class.name} from ) + { + return newBuilder( from, false ); + } + + public static Builder newBuilder( ${class.name} from, boolean forceCopy ) + { + return new Builder( from, forceCopy ); + } + + public static class Builder + #if ( $class.superClass ) + extends ${class.superClass}.Builder + #end + { + ${class.name} base; + #if ( $class == $root ) + String modelEncoding; + #end + #foreach ( $field in $class.getFields($version) ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type == 'boolean' ) + Boolean ${field.name}; + #elseif ( $type == 'int' ) + Integer ${field.name}; + #else + ${type} ${field.name}; + #end + #end + + Builder( boolean withDefaults ) + { + #if ( $class.superClass ) + super( withDefaults ); + #end + if ( withDefaults ) + { + #foreach ( $field in $class.getFields($version) ) + #if ( $field.defaultValue ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $field.type == "String" ) + this.${field.name} = "${field.defaultValue}"; + #elseif ( $field.type != "java.util.List" && $field.type != "java.util.Properties" ) + this.${field.name} = ${field.defaultValue}; + #end + #end + #end + } + } + + Builder( ${class.name} base, boolean forceCopy ) + { + #if ( $class.superClass ) + super( base, forceCopy ); + #end + if ( forceCopy ) + { + #foreach ( $field in $class.getFields($version) ) + this.${field.name} = base.${field.name}; + #end + } + else + { + this.base = base; + } + } + + #if ( $class == $root ) + public Builder modelEncoding( String modelEncoding ) + { + this.modelEncoding = modelEncoding; + return this; + } + + #end + #foreach ( $field in $allFields ) + public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + { + this.${field.name} = ${field.name}; + return this; + } + + #end + + public ${class.name} build() + { + if ( base != null + #foreach ( $field in $allFields ) + && ( ${field.name} == null || ${field.name} == base.${field.name} ) + #end + ) + { + return base; + } + return new ${class.name}( + #if ( $class == $root ) + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + #end + #foreach ( $field in $allFields ) + #if ( $field == ${allFields[${allFields.size()} - 1]} ) + #set ( $sep = "" ) + #else + #set ( $sep = "," ) + #end + #if ( $field.type == "java.util.List" ) + ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() )${sep} + #elseif ( $field.type == "java.util.Properties" ) + new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) )${sep} + #elseif ( $field.type == "boolean" || $field.type == "int" ) + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} + #else + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} + #end + #end + ); + } + } + + #foreach ( $cs in $class.allCodeSegments ) +$cs.code + #end +} + #end +#end diff --git a/maven-plugin-api/src/main/mdo/reader.vm b/maven-plugin-api/src/main/mdo/reader.vm new file mode 100644 index 000000000000..5799f516d462 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/reader.vm @@ -0,0 +1,901 @@ +#* + 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. +*# +#set ( $basePackage = "${model.getDefault('package').getValue()}" ) +#set ( $package = "${basePackage}.io.xpp3" ) +#set ( $className = "${model.name}Xpp3Reader" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( new ContentTransformer() + { + public String transform( String source, String fieldName ) + { + return source; + } + } ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + return getIntegerValue( s, attribute, parser, strict, 0 ); + } //-- int getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean, int ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- ${root.name} read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- ${root.name} read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + List<$field.to> ${field.name} = new ArrayList<>(); + #end + #end + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = checkDuplicate( parser.getName(), parser, parsed ); + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular( $fieldTagName ) ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + ${classLcapName}.${field.name}( ${field.name} ); + #end + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String checkDuplicate( String tagName, XmlPullParser parser, Set parsed ) + throws XmlPullParserException + { +#set( $aliases = { } ) +#set( $flats = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular($fieldTagName) ) + #set ( $dummy = $flats.put( $fieldTagName, "" ) ) + #end + #end +#end +#if ( ! ${aliases.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + tagName = "${entry.value}"; + #end + } +#end +#if ( ! ${flats.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $flats.entrySet() ) + case "${entry.key}": + #end + break; + default: + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + } +#end + return tagName; + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-plugin-api/src/main/mdo/writer.vm b/maven-plugin-api/src/main/mdo/writer.vm new file mode 100644 index 000000000000..8de89ee6fc80 --- /dev/null +++ b/maven-plugin-api/src/main/mdo/writer.vm @@ -0,0 +1,325 @@ +#* + 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. +*# +#set ( $basePackage = "${model.getDefault('package').getValue()}" ) +#set ( $package = "${basePackage}.io.xpp3" ) +#set ( $className = "${model.name}Xpp3Writer" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${field.defaultValue} == "true" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + // TODO: name=${field.name} type=${field.type} + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + for ( T t : list ) + { + writer.write( t ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} diff --git a/maven-resolver-provider/pom.xml b/maven-resolver-provider/pom.xml index 0027e348f4c8..1227764a4fcb 100644 --- a/maven-resolver-provider/pom.xml +++ b/maven-resolver-provider/pom.xml @@ -152,6 +152,15 @@ under the License. org.eclipse.sisu sisu-maven-plugin + + org.apache.maven.plugins + maven-compiler-plugin + + + **/package-info.java + + + diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java index 17fbb1001307..b387e9967182 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/ArtifactDescriptorUtils.java @@ -57,6 +57,7 @@ public static RemoteRepository toRemoteRepository( Repository repository ) return builder.build(); } + public static RepositoryPolicy toRepositoryPolicy( org.apache.maven.model.RepositoryPolicy policy ) { boolean enabled = true; diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java index 3811365e40ed..b77232e8da87 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java @@ -239,7 +239,7 @@ private Model loadPom( RepositorySystemSession session, ArtifactDescriptorReques pomArtifact.getVersion() ) ); } - model = modelBuilder.build( modelRequest ).getEffectiveModel(); + model = new Model( modelBuilder.build( modelRequest ).getEffectiveModel() ); } catch ( ModelBuildingException e ) { diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java index f23bfe4ef8b6..595a7e7056a9 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java @@ -25,10 +25,11 @@ import java.util.Iterator; import java.util.List; import java.util.Set; +import java.util.concurrent.atomic.AtomicReference; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Parent; -import org.apache.maven.model.Repository; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; +import org.apache.maven.api.model.Repository; import org.apache.maven.model.building.ArtifactModelSource; import org.apache.maven.model.building.ModelSource; import org.apache.maven.model.resolution.InvalidRepositoryException; @@ -133,7 +134,8 @@ public void addRepository( final Repository repository, boolean replace ) } List newRepositories = - Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( repository ) ); + Collections.singletonList( ArtifactDescriptorUtils.toRemoteRepository( + new org.apache.maven.model.Repository( repository ) ) ); this.repositories = remoteRepositoryManager.aggregateRepositories( session, repositories, newRepositories, true ); @@ -179,7 +181,7 @@ public ModelSource resolveModel( String groupId, String artifactId, String versi } @Override - public ModelSource resolveModel( final Parent parent ) + public ModelSource resolveModel( final Parent parent, final AtomicReference modified ) throws UnresolvableModelException { try @@ -214,9 +216,13 @@ public ModelSource resolveModel( final Parent parent ) } - parent.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !parent.getVersion().equals( newVersion ) ) + { + modified.set( parent.withVersion( newVersion ) ); + } - return resolveModel( parent.getGroupId(), parent.getArtifactId(), parent.getVersion() ); + return resolveModel( parent.getGroupId(), parent.getArtifactId(), newVersion ); } catch ( final VersionRangeResolutionException e ) { @@ -227,7 +233,7 @@ public ModelSource resolveModel( final Parent parent ) } @Override - public ModelSource resolveModel( final Dependency dependency ) + public ModelSource resolveModel( final Dependency dependency, AtomicReference modified ) throws UnresolvableModelException { try @@ -262,9 +268,13 @@ public ModelSource resolveModel( final Dependency dependency ) } - dependency.setVersion( versionRangeResult.getHighestVersion().toString() ); + String newVersion = versionRangeResult.getHighestVersion().toString(); + if ( !dependency.getVersion().equals( newVersion ) ) + { + modified.set( dependency.withVersion( newVersion ) ); + } - return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion() ); + return resolveModel( dependency.getGroupId(), dependency.getArtifactId(), newVersion ); } catch ( VersionRangeResolutionException e ) { diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java index 629a23f3bea1..49b3aabf8b1e 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/PluginsMetadataInfoProvider.java @@ -39,6 +39,9 @@ interface PluginInfo /** * Returns {@link PluginInfo} corresponding for passed in {@link Artifact}, or {@code null}. + * + * @param artifact the artifact + * @return the plugin info */ PluginInfo getPluginInfo( Artifact artifact ); } diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java index a0a21e9a6002..d12454f94bab 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/RelocatedArtifact.java @@ -152,4 +152,5 @@ public String getMessage() { return message; } + } diff --git a/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java b/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java index 1a4d444de4c0..350e0ab2fa5d 100644 --- a/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java +++ b/maven-resolver-provider/src/test/java/org/apache/maven/repository/internal/DefaultModelResolverTest.java @@ -21,9 +21,10 @@ import java.net.MalformedURLException; import java.util.Arrays; +import java.util.concurrent.atomic.AtomicReference; -import org.apache.maven.model.Dependency; -import org.apache.maven.model.Parent; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Parent; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.UnresolvableModelException; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; @@ -57,14 +58,14 @@ public DefaultModelResolverTest() @Test public void testResolveParentThrowsUnresolvableModelExceptionWhenNotFound() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "0" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "0" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertTrue( e.getMessage().startsWith( "Could not find artifact ut.simple:artifact:pom:0 in repo" ) ); @@ -73,14 +74,14 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNotFound() thro @Test public void testResolveParentThrowsUnresolvableModelExceptionWhenNoMatchingVersionFound() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "[2.0,2.1)" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[2.0,2.1)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertEquals( "No versions matched the requested parent version range '[2.0,2.1)'", @@ -90,14 +91,14 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenNoMatchingVersi @Test public void testResolveParentThrowsUnresolvableModelExceptionWhenUsingRangesWithoutUpperBound() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "[1.0,)" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[1.0,)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( parent ), + () -> newModelResolver().resolveModel( parent, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested parent version range '[1.0,)' does not specify an upper bound", e.getMessage() ); @@ -106,38 +107,40 @@ public void testResolveParentThrowsUnresolvableModelExceptionWhenUsingRangesWith @Test public void testResolveParentSuccessfullyResolvesExistingParentWithoutRange() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "1.0" ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "1.0" ).build(); - assertNotNull( this.newModelResolver().resolveModel( parent ) ); + assertNotNull( this.newModelResolver().resolveModel( parent, new AtomicReference<>() ) ); assertEquals( "1.0", parent.getVersion() ); } @Test public void testResolveParentSuccessfullyResolvesExistingParentUsingHighestVersion() throws Exception { - final Parent parent = new Parent(); - parent.setGroupId( "ut.simple" ); - parent.setArtifactId( "artifact" ); - parent.setVersion( "(,2.0)" ); - - assertNotNull( this.newModelResolver().resolveModel( parent ) ); - assertEquals( "1.0", parent.getVersion() ); + final Parent parent = Parent.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "(,2.0)" ).build(); + + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( parent, modified ) ); + assertNotNull( modified.get() ); + assertEquals( "1.0", modified.get().getVersion() ); } @Test public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNotFound() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "0" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "0" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertNotNull( e.getMessage() ); assertTrue( e.getMessage().startsWith( "Could not find artifact ut.simple:artifact:pom:0 in repo" ) ); @@ -146,14 +149,14 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNotFound() @Test public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNoMatchingVersionFound() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "[2.0,2.1)" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[2.0,2.1)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "No versions matched the requested dependency version range '[2.0,2.1)'", e.getMessage() ); @@ -162,14 +165,14 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenNoMatchingV @Test public void testResolveDependencyThrowsUnresolvableModelExceptionWhenUsingRangesWithoutUpperBound() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "[1.0,)" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "[1.0,)" ).build(); UnresolvableModelException e = assertThrows( UnresolvableModelException.class, - () -> newModelResolver().resolveModel( dependency ), + () -> newModelResolver().resolveModel( dependency, new AtomicReference<>() ), "Expected 'UnresolvableModelException' not thrown." ); assertEquals( "The requested dependency version range '[1.0,)' does not specify an upper bound", e.getMessage() ); @@ -178,25 +181,27 @@ public void testResolveDependencyThrowsUnresolvableModelExceptionWhenUsingRanges @Test public void testResolveDependencySuccessfullyResolvesExistingDependencyWithoutRange() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "1.0" ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "1.0" ).build(); - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); + assertNotNull( this.newModelResolver().resolveModel( dependency, new AtomicReference<>() ) ); assertEquals( "1.0", dependency.getVersion() ); } @Test public void testResolveDependencySuccessfullyResolvesExistingDependencyUsingHighestVersion() throws Exception { - final Dependency dependency = new Dependency(); - dependency.setGroupId( "ut.simple" ); - dependency.setArtifactId( "artifact" ); - dependency.setVersion( "(,2.0)" ); - - assertNotNull( this.newModelResolver().resolveModel( dependency ) ); - assertEquals( "1.0", dependency.getVersion() ); + final Dependency dependency = Dependency.newBuilder() + .groupId( "ut.simple" ) + .artifactId( "artifact" ) + .version( "(,2.0)" ).build(); + + AtomicReference modified = new AtomicReference<>(); + assertNotNull( this.newModelResolver().resolveModel( dependency, modified ) ); + assertNotNull( modified.get() ); + assertEquals( "1.0", modified.get().getVersion() ); } private ModelResolver newModelResolver() throws ComponentLookupException, MalformedURLException 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 0d1a1b601e7e..183d4f77b878 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 @@ -33,8 +33,8 @@ 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.api.settings.Settings; +import org.apache.maven.api.settings.TrackableBase; import org.apache.maven.settings.io.SettingsParseException; import org.apache.maven.settings.io.SettingsReader; import org.apache.maven.settings.io.SettingsWriter; @@ -106,7 +106,7 @@ public SettingsBuildingResult build( SettingsBuildingRequest request ) getSettingsSource( request.getUserSettingsFile(), request.getUserSettingsSource() ); Settings userSettings = readSettings( userSettingsSource, request, problems ); - settingsMerger.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL ); + userSettings = settingsMerger.merge( userSettings, globalSettings, TrackableBase.GLOBAL_LEVEL ); problems.setSource( "" ); @@ -119,7 +119,7 @@ public SettingsBuildingResult build( SettingsBuildingRequest request ) File file = new File( localRepository ); if ( !file.isAbsolute() && file.getPath().startsWith( File.separator ) ) { - userSettings.setLocalRepository( file.getAbsolutePath() ); + userSettings = userSettings.withLocalRepository( file.getAbsolutePath() ); } } @@ -165,7 +165,7 @@ private Settings readSettings( Source settingsSource, SettingsBuildingRequest re { if ( settingsSource == null ) { - return new Settings(); + return Settings.newInstance(); } problems.setSource( settingsSource.getLocation() ); @@ -194,13 +194,13 @@ private Settings readSettings( Source settingsSource, SettingsBuildingRequest re { problems.add( SettingsProblem.Severity.FATAL, "Non-parseable settings " + settingsSource.getLocation() + ": " + e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e ); - return new Settings(); + return Settings.newInstance(); } catch ( IOException e ) { problems.add( SettingsProblem.Severity.FATAL, "Non-readable settings " + settingsSource.getLocation() + ": " + e.getMessage(), -1, -1, e ); - return new Settings(); + return Settings.newInstance(); } settingsValidator.validate( settings, problems ); diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java index 48456e5d6527..4dc59d7e275f 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/DefaultSettingsBuildingResult.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Settings; /** * Collects the output of the settings builder. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java index 43b2359fac08..d2c2c11ebcb2 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/building/SettingsBuildingResult.java @@ -21,7 +21,7 @@ import java.util.List; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Settings; /** * Collects the output of the settings builder. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java index 7d6c8b9b6623..bd0e21b80f7b 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecrypter.java @@ -26,8 +26,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; import org.apache.maven.settings.building.DefaultSettingsProblem; import org.apache.maven.settings.building.SettingsProblem; import org.apache.maven.settings.building.SettingsProblem.Severity; @@ -61,13 +61,9 @@ public SettingsDecryptionResult decrypt( SettingsDecryptionRequest request ) for ( Server server : request.getServers() ) { - server = server.clone(); - - servers.add( server ); - try { - server.setPassword( decrypt( server.getPassword() ) ); + server = server.withPassword( decrypt( server.getPassword() ) ); } catch ( SecDispatcherException e ) { @@ -77,32 +73,32 @@ public SettingsDecryptionResult decrypt( SettingsDecryptionRequest request ) try { - server.setPassphrase( decrypt( server.getPassphrase() ) ); + server = server.withPassphrase( decrypt( server.getPassphrase() ) ); } catch ( SecDispatcherException e ) { problems.add( new DefaultSettingsProblem( "Failed to decrypt passphrase for server " + server.getId() + ": " + e.getMessage(), Severity.ERROR, "server: " + server.getId(), -1, -1, e ) ); } + + servers.add( server ); } List proxies = new ArrayList<>(); for ( Proxy proxy : request.getProxies() ) { - proxy = proxy.clone(); - - proxies.add( proxy ); - try { - proxy.setPassword( decrypt( proxy.getPassword() ) ); + proxy = proxy.withPassword( decrypt( proxy.getPassword() ) ); } catch ( SecDispatcherException e ) { problems.add( new DefaultSettingsProblem( "Failed to decrypt password for proxy " + proxy.getId() + ": " + e.getMessage(), Severity.ERROR, "proxy: " + proxy.getId(), -1, -1, e ) ); } + + proxies.add( proxy ); } return new DefaultSettingsDecryptionResult( servers, proxies, problems ); diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java index 9cb49ac40da2..4281a6c8c8e4 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionRequest.java @@ -23,9 +23,9 @@ import java.util.Arrays; import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; +import org.apache.maven.api.settings.Settings; /** * Collects parameters that control the decryption of settings. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java index ccdad196db25..d52f126960cc 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/DefaultSettingsDecryptionResult.java @@ -22,8 +22,8 @@ import java.util.ArrayList; import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; import org.apache.maven.settings.building.SettingsProblem; /** diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java index b344a99ed928..33c61a6aef87 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionRequest.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; /** * Collects parameters that control the decryption of settings. diff --git a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java index 5b7b1f4b5a31..a8d88b65b980 100644 --- a/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java +++ b/maven-settings-builder/src/main/java/org/apache/maven/settings/crypto/SettingsDecryptionResult.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; import org.apache.maven.settings.building.SettingsProblem; /** 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 4ce48dd0acdf..7662abc68099 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 @@ -29,8 +29,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.io.xpp3.SettingsXpp3Reader; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.v4.SettingsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 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 54f626a22e60..74bbfe4bbc5b 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 @@ -30,8 +30,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Settings; -import org.apache.maven.settings.io.xpp3.SettingsXpp3Writer; +import org.apache.maven.api.settings.Settings; +import org.apache.maven.settings.v4.SettingsXpp3Writer; import org.codehaus.plexus.util.WriterFactory; /** 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 7817df6577bc..802d857706c2 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 @@ -25,7 +25,7 @@ import java.io.Reader; import java.util.Map; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.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 54bfcf0ce1ad..d6444bc28fcc 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 @@ -25,7 +25,7 @@ import java.io.Writer; import java.util.Map; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.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 cb5f6c166f1f..0eec227744e0 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 @@ -23,9 +23,11 @@ import java.util.HashMap; import java.util.List; import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; -import org.apache.maven.settings.IdentifiableBase; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.IdentifiableBase; +import org.apache.maven.api.settings.Settings; import org.codehaus.plexus.util.StringUtils; /** @@ -40,66 +42,65 @@ public class MavenSettingsMerger * @param recessive * @param recessiveSourceLevel */ - public void merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) + public Settings merge( Settings dominant, Settings recessive, String recessiveSourceLevel ) { - if ( dominant == null || recessive == null ) + if ( dominant == null ) { - return; + return recessive; + } + else if ( recessive == null ) + { + return dominant; } recessive.setSourceLevel( recessiveSourceLevel ); + Settings.Builder merged = Settings.newBuilder(); + List dominantActiveProfiles = dominant.getActiveProfiles(); List recessiveActiveProfiles = recessive.getActiveProfiles(); - + List mergedActiveProfiles = new ArrayList<>(); if ( recessiveActiveProfiles != null ) { - if ( dominantActiveProfiles == null ) - { - dominantActiveProfiles = new ArrayList<>(); - dominant.setActiveProfiles( dominantActiveProfiles ); - } - for ( String profileId : recessiveActiveProfiles ) { - if ( !dominantActiveProfiles.contains( profileId ) ) + if ( dominantActiveProfiles == null || !dominantActiveProfiles.contains( profileId ) ) { - dominantActiveProfiles.add( profileId ); + mergedActiveProfiles.add( profileId ); } } } + merged.activeProfiles( mergedActiveProfiles ); List dominantPluginGroupIds = dominant.getPluginGroups(); - List recessivePluginGroupIds = recessive.getPluginGroups(); - + List mergedPluginGroupIds = new ArrayList<>(); if ( recessivePluginGroupIds != null ) { - if ( dominantPluginGroupIds == null ) + if ( dominantPluginGroupIds != null ) { - dominantPluginGroupIds = new ArrayList<>(); - dominant.setPluginGroups( dominantPluginGroupIds ); + mergedPluginGroupIds.addAll( dominantPluginGroupIds ); } - for ( String pluginGroupId : recessivePluginGroupIds ) { - if ( !dominantPluginGroupIds.contains( pluginGroupId ) ) + if ( dominantPluginGroupIds == null || !dominantPluginGroupIds.contains( pluginGroupId ) ) { - dominantPluginGroupIds.add( pluginGroupId ); + mergedPluginGroupIds.add( pluginGroupId ); } } } + merged.pluginGroups( mergedPluginGroupIds ); - if ( StringUtils.isEmpty( dominant.getLocalRepository() ) ) - { - dominant.setLocalRepository( recessive.getLocalRepository() ); - } + String localRepository = StringUtils.isEmpty( dominant.getLocalRepository() ) + ? recessive.getLocalRepository() : dominant.getLocalRepository(); + merged.localRepository( localRepository ); - shallowMergeById( dominant.getMirrors(), recessive.getMirrors(), recessiveSourceLevel ); - shallowMergeById( dominant.getServers(), recessive.getServers(), recessiveSourceLevel ); - shallowMergeById( dominant.getProxies(), recessive.getProxies(), recessiveSourceLevel ); - shallowMergeById( dominant.getProfiles(), recessive.getProfiles(), recessiveSourceLevel ); + 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(); } /** @@ -107,23 +108,22 @@ public void merge( Settings dominant, Settings recessive, String recessiveSource * @param recessive * @param recessiveSourceLevel */ - private static void shallowMergeById( List dominant, List recessive, - String recessiveSourceLevel ) + private static List shallowMergeById( + List dominant, List recessive, String recessiveSourceLevel ) { - Map dominantById = mapById( dominant ); - final List identifiables = new ArrayList<>( recessive.size() ); - + Set dominantIds = dominant.stream().map( IdentifiableBase::getId ).collect( Collectors.toSet() ); + final List merged = new ArrayList<>( dominant.size() + recessive.size() ); + merged.addAll( dominant ); for ( T identifiable : recessive ) { - if ( !dominantById.containsKey( identifiable.getId() ) ) + if ( !dominantIds.contains( identifiable.getId() ) ) { identifiable.setSourceLevel( recessiveSourceLevel ); - - identifiables.add( identifiable ); + merged.add( identifiable ); } } - - dominant.addAll( 0, identifiables ); + merged.addAll( dominant ); + return merged; } /** 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 f0886421a3f6..05526df0ef3f 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 @@ -26,12 +26,12 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.settings.Mirror; -import org.apache.maven.settings.Profile; -import org.apache.maven.settings.Repository; -import org.apache.maven.settings.Proxy; -import org.apache.maven.settings.Server; -import org.apache.maven.settings.Settings; +import org.apache.maven.api.settings.Mirror; +import org.apache.maven.api.settings.Profile; +import org.apache.maven.api.settings.Repository; +import org.apache.maven.api.settings.Proxy; +import org.apache.maven.api.settings.Server; +import org.apache.maven.api.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 79745ecaf14e..887229aa41cf 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 @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.settings.Settings; +import org.apache.maven.api.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 c23ebd2120de..0171af1019cb 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 @@ -20,14 +20,16 @@ */ import java.util.ArrayList; +import java.util.Arrays; +import java.util.Collections; import java.util.List; -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.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.building.SettingsProblem.Severity; import org.apache.maven.settings.building.SettingsProblemCollector; import org.junit.jupiter.api.AfterEach; @@ -67,26 +69,29 @@ private void assertContains( String msg, String substring ) @Test public void testValidate() { - Settings model = new Settings(); - Profile prof = new Profile(); - prof.setId( "xxx" ); - model.addProfile( prof ); + Profile prof = Profile.newInstance().withId( "xxx" ); + Settings model = Settings.newInstance().withProfiles( Collections.singletonList( prof ) ); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 0, problems.messages.size() ); - Repository repo = new Repository(); - prof.addRepository( repo ); + Repository repo = Repository.newInstance(); + prof = prof.withRepositories( Collections.singletonList( repo ) ); + model = model.withProfiles( Collections.singletonList( prof ) ); problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 2, problems.messages.size() ); - repo.setUrl( "http://xxx.xxx.com" ); + repo = repo.withUrl( "http://xxx.xxx.com" ); + prof = prof.withRepositories( Collections.singletonList( repo ) ); + model = model.withProfiles( Collections.singletonList( prof ) ); problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 1, problems.messages.size() ); - repo.setId( "xxx" ); + repo = repo.withId( "xxx" ); + prof = prof.withRepositories( Collections.singletonList( repo ) ); + model = model.withProfiles( Collections.singletonList( prof ) ); problems = new SimpleProblemCollector(); validator.validate( model, problems ); assertEquals( 0, problems.messages.size() ); @@ -96,15 +101,9 @@ public void testValidate() public void testValidateMirror() throws Exception { - 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 ); + 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(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -119,16 +118,10 @@ public void testValidateMirror() public void testValidateRepository() throws Exception { - 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 ); + 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(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -145,13 +138,9 @@ public void testValidateRepository() public void testValidateUniqueServerId() throws Exception { - Settings settings = new Settings(); - Server server1 = new Server(); - server1.setId( "test" ); - settings.addServer( server1 ); - Server server2 = new Server(); - server2.setId( "test" ); - settings.addServer( server2 ); + Server server1 = Server.newBuilder().id( "test" ).build(); + Server server2 = Server.newBuilder().id( "test" ).build(); + Settings settings = Settings.newBuilder().servers( Arrays.asList( server1, server2 ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -164,13 +153,9 @@ public void testValidateUniqueServerId() public void testValidateUniqueProfileId() throws Exception { - Settings settings = new Settings(); - Profile profile1 = new Profile(); - profile1.setId( "test" ); - settings.addProfile( profile1 ); - Profile profile2 = new Profile(); - profile2.setId( "test" ); - settings.addProfile( profile2 ); + Profile profile1 = Profile.newBuilder().id( "test" ).build(); + Profile profile2 = Profile.newBuilder().id( "test" ).build(); + Settings settings = Settings.newBuilder().profiles( Arrays.asList( profile1, profile2 ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -183,18 +168,10 @@ public void testValidateUniqueProfileId() public void testValidateUniqueRepositoryId() throws Exception { - 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 ); + 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(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); @@ -205,21 +182,31 @@ public void testValidateUniqueRepositoryId() @Test public void testValidateUniqueProxyId() - throws Exception + throws Exception + { + Proxy proxy = Proxy.newBuilder().id( "foo" ).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 foo" ); + + } + + @Test + public void testValidateUniqueProxyNullId() + throws Exception { - Settings settings = new Settings(); - Proxy proxy = new Proxy(); - String id = null; - proxy.setId( id ); - proxy.setHost("www.example.com"); - settings.addProxy( proxy ); - settings.addProxy( proxy ); + 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 " + id ); + + " but found duplicate proxy with id null" ); } @@ -227,9 +214,8 @@ public void testValidateUniqueProxyId() public void testValidateProxy() throws Exception { - Settings settings = new Settings(); - Proxy proxy1 = new Proxy(); - settings.addProxy( proxy1 ); + Proxy proxy = Proxy.newBuilder().build(); + Settings settings = Settings.newBuilder().proxies( Collections.singletonList( proxy ) ).build(); SimpleProblemCollector problems = new SimpleProblemCollector(); validator.validate( settings, problems ); diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml index 4405e5c89799..d685b139dbfb 100644 --- a/maven-settings/pom.xml +++ b/maven-settings/pom.xml @@ -38,19 +38,71 @@ under the License. org.codehaus.plexus plexus-utils + + org.apache.maven + maven-api-settings + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT + - org.codehaus.modello - modello-maven-plugin - - 1.2.0 - - src/main/mdo/settings.mdo - - + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy-model + generate-sources + + copy + + + + + org.apache.maven + maven-api-settings + 4.0.0-alpha-1-SNAPSHOT + mdo + target/mdo/ + settings.mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + + velocity + generate-sources + + velocity + + + 4.0.0 + + target/mdo/settings.mdo + + + + + + + + + + diff --git a/maven-settings/src/main/java/org/apache/maven/settings/WrapperList.java b/maven-settings/src/main/java/org/apache/maven/settings/WrapperList.java new file mode 100644 index 000000000000..83c3b5fab4ab --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/WrapperList.java @@ -0,0 +1,129 @@ +package org.apache.maven.settings; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperList extends AbstractList +{ + private final Supplier> getter; + private final Consumer> setter; + private final Function mapper; + private final Function revMapper; + + WrapperList( List list, Function mapper, Function revMapper ) + { + this( () -> list, null, mapper, revMapper ); + } + + WrapperList( Supplier> getter, Consumer> setter, + Function mapper, Function revMapper ) + { + this.getter = getter; + this.setter = setter; + this.mapper = mapper; + this.revMapper = revMapper; + } + + @Override + public T get( int index ) + { + return mapper.apply( getter.get().get( index ) ); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean add( T t ) + { + Objects.requireNonNull( t ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + boolean ret = list.add( revMapper.apply( t ) ); + setter.accept( list ); + return ret; + } + else + { + return getter.get().add( revMapper.apply( t ) ); + } + } + + @Override + public T set( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.set( index, revMapper.apply( element ) ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().set( index, revMapper.apply( element ) ) ); + } + } + + @Override + public void add( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + list.add( index, revMapper.apply( element ) ); + setter.accept( list ); + } + else + { + getter.get().add( index, revMapper.apply( element ) ); + } + } + + @Override + public T remove( int index ) + { + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.remove( index ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().remove( index ) ); + } + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/WrapperProperties.java b/maven-settings/src/main/java/org/apache/maven/settings/WrapperProperties.java new file mode 100644 index 000000000000..cd3ef0b84eaa --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/WrapperProperties.java @@ -0,0 +1,356 @@ +package org.apache.maven.settings; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class WrapperProperties extends Properties +{ + + final Supplier getter; + final Consumer setter; + + public WrapperProperties( Supplier getter, Consumer setter ) + { + this.getter = getter; + this.setter = setter; + } + + @Override + public String getProperty( String key ) + { + return getter.get().getProperty( key ); + } + + @Override + public String getProperty( String key, String defaultValue ) + { + return getter.get().getProperty( key, defaultValue ); + } + + @Override + public Enumeration propertyNames() + { + return getter.get().propertyNames(); + } + + @Override + public Set stringPropertyNames() + { + return getter.get().stringPropertyNames(); + } + + @Override + public void list( PrintStream out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void list( PrintWriter out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean isEmpty() + { + return getter.get().isEmpty(); + } + + @Override + public Enumeration keys() + { + return getter.get().keys(); + } + + @Override + public Enumeration elements() + { + return getter.get().elements(); + } + + @Override + public boolean contains( Object value ) + { + return getter.get().contains( value ); + } + + @Override + public boolean containsValue( Object value ) + { + return getter.get().containsValue( value ); + } + + @Override + public boolean containsKey( Object key ) + { + return getter.get().containsKey( key ); + } + + @Override + public Object get( Object key ) + { + return getter.get().get( key ); + } + + @Override + public synchronized String toString() + { + return getter.get().toString(); + } + + @Override + public Set keySet() + { + return getter.get().keySet(); + } + + @Override + public Collection values() + { + return getter.get().values(); + } + + @Override + public Set> entrySet() + { + return getter.get().entrySet(); + } + + @Override + public synchronized boolean equals( Object o ) + { + if ( o instanceof WrapperProperties ) + { + o = ( (WrapperProperties) o ).getter.get(); + } + return getter.get().equals( o ); + } + + @Override + public synchronized int hashCode() + { + return getter.get().hashCode(); + } + + @Override + public Object getOrDefault( Object key, Object defaultValue ) + { + return getter.get().getOrDefault( key, defaultValue ); + } + + @Override + public synchronized void forEach( BiConsumer action ) + { + getter.get().forEach( action ); + } + + interface WriteOp + { + T perform( Properties props ); + } + + interface WriteOpVoid + { + void perform( Properties props ); + } + + private T writeOperation( WriteOp runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + T ret = runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + return ret; + } + + private void writeOperationVoid( WriteOpVoid runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + } + + @Override + public synchronized Object setProperty( String key, String value ) + { + return writeOperation( p -> p.setProperty( key, value ) ); + } + + @Override + public synchronized Object put( Object key, Object value ) + { + return writeOperation( p -> p.put( key, value ) ); + } + + @Override + public synchronized Object remove( Object key ) + { + return writeOperation( p -> p.remove( key ) ); + } + + @Override + public synchronized void putAll( Map t ) + { + writeOperationVoid( p -> p.putAll( t ) ); + } + + @Override + public synchronized void clear() + { + writeOperationVoid( Properties::clear ); + } + + @Override + public synchronized void replaceAll( BiFunction function ) + { + writeOperationVoid( p -> p.replaceAll( function ) ); + } + + @Override + public synchronized Object putIfAbsent( Object key, Object value ) + { + return writeOperation( p -> p.putIfAbsent( key, value ) ); + } + + @Override + public synchronized boolean remove( Object key, Object value ) + { + return writeOperation( p -> p.remove( key, value ) ); + } + + @Override + public synchronized boolean replace( Object key, Object oldValue, Object newValue ) + { + return writeOperation( p -> p.replace( key, oldValue, newValue ) ); + } + + @Override + public synchronized Object replace( Object key, Object value ) + { + return writeOperation( p -> p.replace( key, value ) ); + } + + @Override + public synchronized Object computeIfAbsent( Object key, Function mappingFunction ) + { + return writeOperation( p -> p.computeIfAbsent( key, mappingFunction ) ); + } + + @Override + public synchronized Object computeIfPresent( Object key, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.computeIfPresent( key, remappingFunction ) ); + } + + @Override + public synchronized Object compute( Object key, BiFunction remappingFunction ) + { + return writeOperation( p -> p.compute( key, remappingFunction ) ); + } + + @Override + public synchronized Object merge( Object key, Object value, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.merge( key, value, remappingFunction ) ); + } + + @Override + public synchronized void load( Reader reader ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void load( InputStream inStream ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void save( OutputStream out, String comments ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( Writer writer, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( OutputStream out, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void loadFromXML( InputStream in ) throws IOException, InvalidPropertiesFormatException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException + { + throw new UnsupportedOperationException(); + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Reader.java b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Reader.java new file mode 100644 index 000000000000..750a45f7cdce --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Reader.java @@ -0,0 +1,167 @@ +package org.apache.maven.settings.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import org.apache.maven.settings.Settings; +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class SettingsXpp3Reader +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public SettingsXpp3Reader() + { + this( ( source, fieldName ) -> source ); + } + + public SettingsXpp3Reader( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities + ? new MXParser( EntityReplacementMap.defaultEntityReplacementMap ) : new MXParser(); + parser.setInput( reader ); + return read( parser, strict ); + } //-- Model read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model + */ + public Settings read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- Model read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- Model read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- Model read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Settings + */ + public Settings read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + org.apache.maven.settings.v4.SettingsXpp3Reader reader = contentTransformer != null + ? new org.apache.maven.settings.v4.SettingsXpp3Reader( contentTransformer::transform ) + : new org.apache.maven.settings.v4.SettingsXpp3Reader(); + reader.setAddDefaultEntities( addDefaultEntities ); + org.apache.maven.api.settings.Settings settings = reader.read( parser, strict ); + return new Settings( settings ); + } //-- Model read( XmlPullParser, boolean ) + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Writer.java b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Writer.java new file mode 100644 index 000000000000..c1710044046a --- /dev/null +++ b/maven-settings/src/main/java/org/apache/maven/settings/io/xpp3/SettingsXpp3Writer.java @@ -0,0 +1,84 @@ +package org.apache.maven.settings.io.xpp3; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.OutputStream; +import java.io.Writer; + +import org.apache.maven.settings.Settings; + +public class SettingsXpp3Writer +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param settings a settings object. + * @throws IOException java.io.IOException if any. + */ + public void write( Writer writer, Settings settings ) + throws IOException + { + org.apache.maven.settings.v4.SettingsXpp3Writer xw = new org.apache.maven.settings.v4.SettingsXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( writer, settings.getDelegate() ); + } //-- void write( Writer, Model ) + + /** + * Method write. + * + * @param stream a stream object. + * @param settings a settings object. + * @throws IOException java.io.IOException if any. + */ + public void write( OutputStream stream, Settings settings ) + throws IOException + { + org.apache.maven.settings.v4.SettingsXpp3Writer xw = new org.apache.maven.settings.v4.SettingsXpp3Writer(); + xw.setFileComment( fileComment ); + xw.write( stream, settings.getDelegate() ); + } //-- void write( OutputStream, Model ) + +} diff --git a/maven-settings/src/main/mdo/merger.vm b/maven-settings/src/main/mdo/merger.vm new file mode 100644 index 000000000000..6056f0c75850 --- /dev/null +++ b/maven-settings/src/main/mdo/merger.vm @@ -0,0 +1,358 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.settings" ) +#set ( $package = "org.apache.maven.settings.v4" ) +#set ( $className = "${model.name}Merger" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * 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 + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @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 null. + */ + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return merge${root.name}( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.getFields($version) ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( src != null ) + { + Properties tgt = target.get${capField}(); + if ( tgt == null ) + { + builder.${field.name}( src ); + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-settings/src/main/mdo/model-v3.vm b/maven-settings/src/main/mdo/model-v3.vm new file mode 100644 index 000000000000..9cbec77ec3e9 --- /dev/null +++ b/maven-settings/src/main/mdo/model-v3.vm @@ -0,0 +1,236 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.settings" ) +#set ( $package = "${basePackage}" ) +#set ( $wrapPackage = "org.apache.maven.api.settings" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end + #end + #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #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.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 + ">" ) ) + #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 +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable, Cloneable +{ + + #if ( ! $class.superClass ) + ${wrapPackage}.${class.name} delegate; + #end + + public ${class.name}() + { + this( ${wrapPackage}.${class.name}.newInstance() ); + } + + public ${class.name}( ${wrapPackage}.${class.name} delegate ) + { + #if ( $class.superClass ) + super( delegate ); + #else + this.delegate = delegate; + #end + } + + public ${class.name} clone() + { + return new ${class.name}( getDelegate() ); + } + + #if ( $class.superClass ) + @Override + #end + public ${wrapPackage}.${class.name} getDelegate() + { + #if ( $class.superClass ) + return ( ${wrapPackage}.${class.name} ) delegate; + #else + return delegate; + #end + } + + #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 ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList<${field.to}, ${wrapPackage}.${field.to}>( + getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), + ${field.to}::new, ${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( 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; + #else + return getDelegate().${pfx}${cap}(); + #end + } + + public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + { + #if ( $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() ); + #else + delegate = getDelegate().with${cap}( ${field.name} ); + #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" ) + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) + .collect( Collectors.toList() ) ); + #else + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) + .collect( Collectors.toList() ) ); + #end + } + + #end + #end + public static List<${wrapPackage}.${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<${wrapPackage}.${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/maven-settings/src/main/mdo/reader.vm b/maven-settings/src/main/mdo/reader.vm new file mode 100644 index 000000000000..6cc754abe49a --- /dev/null +++ b/maven-settings/src/main/mdo/reader.vm @@ -0,0 +1,901 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.settings" ) +#set ( $package = "org.apache.maven.settings.v4" ) +#set ( $className = "${model.name}Xpp3Reader" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( new ContentTransformer() + { + public String transform( String source, String fieldName ) + { + return source; + } + } ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + return getIntegerValue( s, attribute, parser, strict, 0 ); + } //-- int getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean, int ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- ${root.name} read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- ${root.name} read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + List<$field.to> ${field.name} = new ArrayList<>(); + #end + #end + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = checkDuplicate( parser.getName(), parser, parsed ); + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular( $fieldTagName ) ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + ${classLcapName}.${field.name}( ${field.name} ); + #end + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String checkDuplicate( String tagName, XmlPullParser parser, Set parsed ) + throws XmlPullParserException + { +#set( $aliases = { } ) +#set( $flats = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular($fieldTagName) ) + #set ( $dummy = $flats.put( $fieldTagName, "" ) ) + #end + #end +#end +#if ( ! ${aliases.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + tagName = "${entry.value}"; + #end + } +#end +#if ( ! ${flats.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $flats.entrySet() ) + case "${entry.key}": + #end + break; + default: + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + } +#end + return tagName; + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-settings/src/main/mdo/writer.vm b/maven-settings/src/main/mdo/writer.vm new file mode 100644 index 000000000000..007ba93384ed --- /dev/null +++ b/maven-settings/src/main/mdo/writer.vm @@ -0,0 +1,325 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.settings" ) +#set ( $package = "org.apache.maven.settings.v4" ) +#set ( $className = "${model.name}Xpp3Writer" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${field.defaultValue} == "true" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + // TODO: name=${field.name} type=${field.type} + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + for ( T t : list ) + { + writer.write( t ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} 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 d1199873a6c7..78d76f6afe83 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 @@ -27,8 +27,8 @@ 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.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.TrackableBase; import org.codehaus.plexus.interpolation.EnvarBasedValueSource; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.RegexBasedInterpolator; @@ -76,11 +76,12 @@ public ToolchainsBuildingResult build( ToolchainsBuildingRequest request ) PersistedToolchains userToolchains = readToolchains( request.getUserToolchainsSource(), request, problems ); - toolchainsMerger.merge( userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL ); + PersistedToolchains merged = toolchainsMerger.merge( + userToolchains, globalToolchains, TrackableBase.GLOBAL_LEVEL ); problems.setSource( "" ); - userToolchains = interpolate( userToolchains, problems ); + merged = interpolate( merged, problems ); if ( hasErrors( problems.getProblems() ) ) { @@ -88,7 +89,7 @@ public ToolchainsBuildingResult build( ToolchainsBuildingRequest request ) } - return new DefaultToolchainsBuildingResult( userToolchains, problems.getProblems() ); + return new DefaultToolchainsBuildingResult( merged, problems.getProblems() ); } private PersistedToolchains interpolate( PersistedToolchains toolchains, ProblemCollector problems ) @@ -160,7 +161,7 @@ private PersistedToolchains readToolchains( Source toolchainsSource, ToolchainsB { if ( toolchainsSource == null ) { - return new PersistedToolchains(); + return PersistedToolchains.newInstance(); } PersistedToolchains toolchains; @@ -187,13 +188,13 @@ private PersistedToolchains readToolchains( Source toolchainsSource, ToolchainsB { problems.add( Problem.Severity.FATAL, "Non-parseable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(), e.getLineNumber(), e.getColumnNumber(), e ); - return new PersistedToolchains(); + return PersistedToolchains.newInstance(); } catch ( IOException e ) { problems.add( Problem.Severity.FATAL, "Non-readable toolchains " + toolchainsSource.getLocation() + ": " + e.getMessage(), -1, -1, e ); - return new PersistedToolchains(); + return PersistedToolchains.newInstance(); } return toolchains; diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java index 2d07a4a03c29..c13ee8b65779 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/DefaultToolchainsBuildingResult.java @@ -23,7 +23,7 @@ import java.util.List; import org.apache.maven.building.Problem; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; /** * Holds the result of the merged toolchains and holds the problems during this build, if any. diff --git a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java index f7c5f71554a8..0d91812148db 100644 --- a/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java +++ b/maven-toolchain-builder/src/main/java/org/apache/maven/toolchain/building/ToolchainsBuildingResult.java @@ -22,7 +22,7 @@ import java.util.List; import org.apache.maven.building.Problem; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; /** * Collects the output of the toolchains builder. 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 25225510fb28..b58995a69f34 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 @@ -29,8 +29,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; 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 51ebdc7a9c41..a9ee7793b9fe 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 @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Writer; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Writer; import javax.inject.Named; import javax.inject.Singleton; 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 44dc2bdc7902..413674a7b85e 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 @@ -25,7 +25,7 @@ import java.io.Reader; import java.util.Map; -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.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 0b15f3451ad8..8e157cd45cd5 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 @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; +import org.apache.maven.api.toolchain.PersistedToolchains; import java.io.IOException; import java.io.Writer; 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 9b6596ea3d38..d081bb52ca45 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 @@ -19,13 +19,14 @@ * under the License. */ +import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.ToolchainModel; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.ToolchainModel; /** * @@ -35,19 +36,20 @@ public class MavenToolchainMerger { - public void merge( PersistedToolchains dominant, PersistedToolchains recessive, String recessiveSourceLevel ) + public PersistedToolchains merge( PersistedToolchains dominant, PersistedToolchains recessive, + String recessiveSourceLevel ) { if ( dominant == null || recessive == null ) { - return; + return dominant; } recessive.setSourceLevel( recessiveSourceLevel ); - shallowMerge( dominant.getToolchains(), recessive.getToolchains(), recessiveSourceLevel ); + return shallowMerge( dominant.getToolchains(), recessive.getToolchains(), recessiveSourceLevel ); } - private void shallowMerge( List dominant, List recessive, + private PersistedToolchains shallowMerge( List dominant, List recessive, String recessiveSourceLevel ) { Map merged = new LinkedHashMap<>(); @@ -67,32 +69,25 @@ private void shallowMerge( List dominant, List r if ( dominantModel == null ) { recessiveModel.setSourceLevel( recessiveSourceLevel ); - dominant.add( recessiveModel ); + merged.put( key, recessiveModel ); } else { - mergeToolchainModelConfiguration( dominantModel, recessiveModel ); + merged.put( key, mergeToolchainModelConfiguration( dominantModel, recessiveModel ) ); } } + return PersistedToolchains.newBuilder() + .toolchains( new ArrayList<>( merged.values() ) ) + .build(); } - protected void mergeToolchainModelConfiguration( ToolchainModel target, - ToolchainModel source ) + protected ToolchainModel mergeToolchainModelConfiguration( ToolchainModel target, + ToolchainModel source ) { - Xpp3Dom src = (Xpp3Dom) source.getConfiguration(); - if ( src != null ) - { - Xpp3Dom tgt = (Xpp3Dom) target.getConfiguration(); - if ( tgt == null ) - { - tgt = Xpp3Dom.mergeXpp3Dom( new Xpp3Dom( src ), tgt ); - } - else - { - tgt = Xpp3Dom.mergeXpp3Dom( tgt, src ); - } - target.setConfiguration( tgt ); - } + Dom src = source.getConfiguration(); + Dom tgt = target.getConfiguration(); + Dom merged = Dom.merge( tgt, src ); + return target.withConfiguration( merged ); } protected Object getToolchainModelKey( ToolchainModel model ) 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 6460aaf0a84e..a64b66af35a6 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 @@ -20,13 +20,13 @@ */ import org.apache.maven.building.StringSource; +import org.apache.maven.internal.xml.Xpp3Dom; 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.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.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; @@ -36,8 +36,10 @@ import java.io.IOException; import java.io.InputStream; +import java.util.Collections; import java.util.HashMap; import java.util.Map; +import java.util.Properties; import static org.junit.jupiter.api.Assertions.assertEquals; import static org.junit.jupiter.api.Assertions.assertNotNull; @@ -87,11 +89,15 @@ public void testBuildRequestWithUserToolchains() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains userResult = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "user_value" ); - userResult.addToolchain( toolchain ); + 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(); doReturn(userResult).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -110,11 +116,15 @@ public void testBuildRequestWithGlobalToolchains() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setGlobalToolchainsSource( new StringSource( "" ) ); - PersistedToolchains globalResult = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "global_value" ); - globalResult.addToolchain( toolchain ); + 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(); doReturn(globalResult).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -134,17 +144,26 @@ public void testBuildRequestWithBothToolchains() request.setGlobalToolchainsSource( new StringSource( "" ) ); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains userResult = new PersistedToolchains(); - ToolchainModel userToolchain = new ToolchainModel(); - userToolchain.setType( "TYPE" ); - userToolchain.addProvide( "key", "user_value" ); - userResult.addToolchain( userToolchain ); - - PersistedToolchains globalResult = new PersistedToolchains(); - ToolchainModel globalToolchain = new ToolchainModel(); - globalToolchain.setType( "TYPE" ); - globalToolchain.addProvide( "key", "global_value" ); - globalResult.addToolchain( globalToolchain ); + 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(); + + 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(); + doReturn(globalResult).doReturn(userResult).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -203,17 +222,19 @@ public void testEnvironmentVariablesAreInterpolated() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains persistedToolchains = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "${env.testKey}" ); - - Xpp3Dom configurationChild = new Xpp3Dom("jdkHome"); - configurationChild.setValue("${env.testKey}"); - Xpp3Dom configuration = new Xpp3Dom("configuration"); - configuration.addChild(configurationChild); - toolchain.setConfiguration(configuration); - persistedToolchains.addToolchain( toolchain ); + Properties props = new Properties(); + props.put( "key", "${env.testKey}" ); + Xpp3Dom configurationChild = new Xpp3Dom("jdkHome", "${env.testKey}", null, null, null); + Xpp3Dom configuration = new Xpp3Dom("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(); + doReturn(persistedToolchains).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -232,12 +253,16 @@ public void testNonExistingEnvironmentVariablesAreNotInterpolated() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains persistedToolchains = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "${env.testNonExistingKey}" ); + 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(); - persistedToolchains.addToolchain( toolchain ); doReturn(persistedToolchains).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); @@ -253,12 +278,16 @@ public void testEnvironmentVariablesWithSpecialCharactersAreInterpolated() ToolchainsBuildingRequest request = new DefaultToolchainsBuildingRequest(); request.setUserToolchainsSource( new StringSource( "" ) ); - PersistedToolchains persistedToolchains = new PersistedToolchains(); - ToolchainModel toolchain = new ToolchainModel(); - toolchain.setType( "TYPE" ); - toolchain.addProvide( "key", "${env.testSpecialCharactersKey}" ); + 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(); - persistedToolchains.addToolchain( toolchain ); doReturn(persistedToolchains).when( toolchainsReader ).read( any( InputStream.class ), ArgumentMatchers.anyMap()); ToolchainsBuildingResult result = toolchainBuilder.build( request ); 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 7bed9a909ad1..fec62506fa90 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 @@ -19,11 +19,11 @@ * under the License. */ -import org.apache.maven.toolchain.model.PersistedToolchains; -import org.apache.maven.toolchain.model.ToolchainModel; -import org.apache.maven.toolchain.model.TrackableBase; -import org.apache.maven.toolchain.model.io.xpp3.MavenToolchainsXpp3Reader; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.api.toolchain.PersistedToolchains; +import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.api.toolchain.TrackableBase; +import org.apache.maven.toolchain.v4.MavenToolchainsXpp3Reader; import org.junit.jupiter.api.Test; import java.io.InputStream; @@ -41,7 +41,7 @@ public void testMergeNulls() { merger.merge( null, null, null ); - PersistedToolchains pt = new PersistedToolchains(); + PersistedToolchains pt = PersistedToolchains.newInstance(); merger.merge( pt, null, null ); merger.merge( null, pt, null ); } @@ -50,15 +50,15 @@ public void testMergeNulls() public void testMergeJdk() throws Exception { - try ( InputStream isDominant = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream isRecessive = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ) ) + 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 ); assertEquals( 2, dominant.getToolchains().size() ); - merger.merge( dominant, recessive, TrackableBase.USER_LEVEL ); - assertEquals( 2, dominant.getToolchains().size() ); + PersistedToolchains merged = merger.merge( dominant, recessive, TrackableBase.USER_LEVEL ); + assertEquals( 2, merged.getToolchains().size() ); } } @@ -66,28 +66,32 @@ public void testMergeJdk() public void testMergeJdkExtra() throws Exception { - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtraIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extra.xml" ) ) + 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 ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtra.getToolchains().size() ); - merger.merge( jdks, jdksExtra, TrackableBase.USER_LEVEL ); - assertEquals( 4, jdks.getToolchains().size() ); + PersistedToolchains merged = merger.merge( jdks, jdksExtra, TrackableBase.USER_LEVEL ); + assertEquals( 4, merged.getToolchains().size() ); + assertEquals( 2, jdks.getToolchains().size() ); assertEquals( 2, jdksExtra.getToolchains().size() ); } - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtraIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extra.xml" ) ) + 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 ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtra.getToolchains().size() ); // switch dominant with recessive - merger.merge( jdksExtra, jdks, TrackableBase.USER_LEVEL ); - assertEquals( 4, jdksExtra.getToolchains().size() ); + PersistedToolchains merged = merger.merge( jdksExtra, jdks, TrackableBase.USER_LEVEL ); + assertEquals( 4, merged.getToolchains().size() ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtra.getToolchains().size() ); } } @@ -95,40 +99,42 @@ public void testMergeJdkExtra() public void testMergeJdkExtend() throws Exception { - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtendIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extend.xml" ) ) + 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 ); assertEquals( 2, jdks.getToolchains().size() ); - merger.merge( jdks, jdksExtend, TrackableBase.USER_LEVEL ); - assertEquals( 2, jdks.getToolchains().size() ); - Xpp3Dom config0 = (Xpp3Dom) jdks.getToolchains().get( 0 ).getConfiguration(); + PersistedToolchains merged = merger.merge( jdks, jdksExtend, TrackableBase.USER_LEVEL ); + assertEquals( 2, merged.getToolchains().size() ); + Dom config0 = merged.getToolchains().get( 0 ).getConfiguration(); assertEquals( "lib/tools.jar", config0.getChild( "toolsJar" ).getValue() ); - assertEquals( 2, config0.getChildCount() ); - Xpp3Dom config1 = (Xpp3Dom) jdks.getToolchains().get( 1 ).getConfiguration(); - assertEquals( 2, config1.getChildCount() ); + assertEquals( 2, config0.getChildren().size() ); + Dom config1 = merged.getToolchains().get( 1 ).getConfiguration(); + assertEquals( 2, config1.getChildren().size() ); assertEquals( "lib/classes.jar", config1.getChild( "toolsJar" ).getValue() ); + assertEquals( 2, jdks.getToolchains().size() ); assertEquals( 2, jdksExtend.getToolchains().size() ); } - try ( InputStream jdksIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks.xml" ); - InputStream jdksExtendIS = ToolchainModel.class.getResourceAsStream( "toolchains-jdks-extend.xml" ) ) + 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 ); assertEquals( 2, jdks.getToolchains().size() ); // switch dominant with recessive - merger.merge( jdksExtend, jdks, TrackableBase.USER_LEVEL ); - assertEquals( 2, jdksExtend.getToolchains().size() ); - Xpp3Dom config0 = (Xpp3Dom) jdksExtend.getToolchains().get( 0 ).getConfiguration(); + PersistedToolchains merged = merger.merge( jdksExtend, jdks, TrackableBase.USER_LEVEL ); + assertEquals( 2, merged.getToolchains().size() ); + Dom config0 = merged.getToolchains().get( 0 ).getConfiguration(); assertEquals( "lib/tools.jar", config0.getChild( "toolsJar" ).getValue() ); - assertEquals( 2, config0.getChildCount() ); - Xpp3Dom config1 = (Xpp3Dom) jdksExtend.getToolchains().get( 1 ).getConfiguration(); - assertEquals( 2, config1.getChildCount() ); + assertEquals( 2, config0.getChildren().size() ); + Dom config1 = merged.getToolchains().get( 1 ).getConfiguration(); + assertEquals( 2, config1.getChildren().size() ); assertEquals( "lib/classes.jar", config1.getChild( "toolsJar" ).getValue() ); assertEquals( 2, jdks.getToolchains().size() ); + assertEquals( 2, jdksExtend.getToolchains().size() ); } } diff --git a/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extend.xml b/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extend.xml similarity index 100% rename from maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extend.xml rename to maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extend.xml diff --git a/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extra.xml b/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extra.xml similarity index 100% rename from maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks-extra.xml rename to maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks-extra.xml diff --git a/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks.xml b/maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks.xml similarity index 100% rename from maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/model/toolchains-jdks.xml rename to maven-toolchain-builder/src/test/resources/org/apache/maven/toolchain/merge/toolchains-jdks.xml diff --git a/maven-toolchain-model/pom.xml b/maven-toolchain-model/pom.xml index cf3237136978..5ade9ba8cb96 100644 --- a/maven-toolchain-model/pom.xml +++ b/maven-toolchain-model/pom.xml @@ -39,19 +39,71 @@ under the License. org.codehaus.plexus plexus-utils + + org.apache.maven + maven-api-toolchain + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT + - org.codehaus.modello - modello-maven-plugin - - 1.1.0 - - src/main/mdo/toolchains.mdo - - + org.apache.maven.plugins + maven-dependency-plugin + 3.2.0 + + + copy-model + generate-sources + + copy + + + + + org.apache.maven + maven-api-toolchain + 4.0.0-alpha-1-SNAPSHOT + mdo + target/mdo/ + toolchains.mdo + + + + + + + + org.apache.maven + modello-plugin-velocity + 4.0.0-alpha-1-SNAPSHOT + + + velocity + generate-sources + + velocity + + + 4.0.0 + + target/mdo/toolchains.mdo + + + + + + + + + + diff --git a/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperList.java b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperList.java new file mode 100644 index 000000000000..5d6f7aa26842 --- /dev/null +++ b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperList.java @@ -0,0 +1,129 @@ +package org.apache.maven.toolchain.model; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.List; +import java.util.Objects; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +class WrapperList extends AbstractList +{ + private final Supplier> getter; + private final Consumer> setter; + private final Function mapper; + private final Function revMapper; + + WrapperList( List list, Function mapper, Function revMapper ) + { + this( () -> list, null, mapper, revMapper ); + } + + WrapperList( Supplier> getter, Consumer> setter, + Function mapper, Function revMapper ) + { + this.getter = getter; + this.setter = setter; + this.mapper = mapper; + this.revMapper = revMapper; + } + + @Override + public T get( int index ) + { + return mapper.apply( getter.get().get( index ) ); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean add( T t ) + { + Objects.requireNonNull( t ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + boolean ret = list.add( revMapper.apply( t ) ); + setter.accept( list ); + return ret; + } + else + { + return getter.get().add( revMapper.apply( t ) ); + } + } + + @Override + public T set( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.set( index, revMapper.apply( element ) ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().set( index, revMapper.apply( element ) ) ); + } + } + + @Override + public void add( int index, T element ) + { + Objects.requireNonNull( element ); + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + list.add( index, revMapper.apply( element ) ); + setter.accept( list ); + } + else + { + getter.get().add( index, revMapper.apply( element ) ); + } + } + + @Override + public T remove( int index ) + { + if ( setter != null ) + { + List list = new ArrayList<>( getter.get() ); + U ret = list.remove( index ); + setter.accept( list ); + return mapper.apply( ret ); + } + else + { + return mapper.apply( getter.get().remove( index ) ); + } + } + +} diff --git a/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperProperties.java b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperProperties.java new file mode 100644 index 000000000000..f3bc6c5ff380 --- /dev/null +++ b/maven-toolchain-model/src/main/java/org/apache/maven/toolchain/model/WrapperProperties.java @@ -0,0 +1,356 @@ +package org.apache.maven.toolchain.model; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.PrintStream; +import java.io.PrintWriter; +import java.io.Reader; +import java.io.Writer; +import java.util.Collection; +import java.util.Enumeration; +import java.util.InvalidPropertiesFormatException; +import java.util.Map; +import java.util.Properties; +import java.util.Set; +import java.util.function.BiConsumer; +import java.util.function.BiFunction; +import java.util.function.Consumer; +import java.util.function.Function; +import java.util.function.Supplier; + +public class WrapperProperties extends Properties +{ + + final Supplier getter; + final Consumer setter; + + public WrapperProperties( Supplier getter, Consumer setter ) + { + this.getter = getter; + this.setter = setter; + } + + @Override + public String getProperty( String key ) + { + return getter.get().getProperty( key ); + } + + @Override + public String getProperty( String key, String defaultValue ) + { + return getter.get().getProperty( key, defaultValue ); + } + + @Override + public Enumeration propertyNames() + { + return getter.get().propertyNames(); + } + + @Override + public Set stringPropertyNames() + { + return getter.get().stringPropertyNames(); + } + + @Override + public void list( PrintStream out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void list( PrintWriter out ) + { + throw new UnsupportedOperationException(); + } + + @Override + public int size() + { + return getter.get().size(); + } + + @Override + public boolean isEmpty() + { + return getter.get().isEmpty(); + } + + @Override + public Enumeration keys() + { + return getter.get().keys(); + } + + @Override + public Enumeration elements() + { + return getter.get().elements(); + } + + @Override + public boolean contains( Object value ) + { + return getter.get().contains( value ); + } + + @Override + public boolean containsValue( Object value ) + { + return getter.get().containsValue( value ); + } + + @Override + public boolean containsKey( Object key ) + { + return getter.get().containsKey( key ); + } + + @Override + public Object get( Object key ) + { + return getter.get().get( key ); + } + + @Override + public synchronized String toString() + { + return getter.get().toString(); + } + + @Override + public Set keySet() + { + return getter.get().keySet(); + } + + @Override + public Collection values() + { + return getter.get().values(); + } + + @Override + public Set> entrySet() + { + return getter.get().entrySet(); + } + + @Override + public synchronized boolean equals( Object o ) + { + if ( o instanceof WrapperProperties ) + { + o = ( (WrapperProperties) o ).getter.get(); + } + return getter.get().equals( o ); + } + + @Override + public synchronized int hashCode() + { + return getter.get().hashCode(); + } + + @Override + public Object getOrDefault( Object key, Object defaultValue ) + { + return getter.get().getOrDefault( key, defaultValue ); + } + + @Override + public synchronized void forEach( BiConsumer action ) + { + getter.get().forEach( action ); + } + + interface WriteOp + { + T perform( Properties props ); + } + + interface WriteOpVoid + { + void perform( Properties props ); + } + + private T writeOperation( WriteOp runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + T ret = runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + return ret; + } + + private void writeOperationVoid( WriteOpVoid runner ) + { + Properties props = new Properties(); + props.putAll( getter.get() ); + runner.perform( props ); + if ( ! props.equals( getter.get() ) ) + { + setter.accept( props ); + } + } + + @Override + public synchronized Object setProperty( String key, String value ) + { + return writeOperation( p -> p.setProperty( key, value ) ); + } + + @Override + public synchronized Object put( Object key, Object value ) + { + return writeOperation( p -> p.put( key, value ) ); + } + + @Override + public synchronized Object remove( Object key ) + { + return writeOperation( p -> p.remove( key ) ); + } + + @Override + public synchronized void putAll( Map t ) + { + writeOperationVoid( p -> p.putAll( t ) ); + } + + @Override + public synchronized void clear() + { + writeOperationVoid( Properties::clear ); + } + + @Override + public synchronized void replaceAll( BiFunction function ) + { + writeOperationVoid( p -> p.replaceAll( function ) ); + } + + @Override + public synchronized Object putIfAbsent( Object key, Object value ) + { + return writeOperation( p -> p.putIfAbsent( key, value ) ); + } + + @Override + public synchronized boolean remove( Object key, Object value ) + { + return writeOperation( p -> p.remove( key, value ) ); + } + + @Override + public synchronized boolean replace( Object key, Object oldValue, Object newValue ) + { + return writeOperation( p -> p.replace( key, oldValue, newValue ) ); + } + + @Override + public synchronized Object replace( Object key, Object value ) + { + return writeOperation( p -> p.replace( key, value ) ); + } + + @Override + public synchronized Object computeIfAbsent( Object key, Function mappingFunction ) + { + return writeOperation( p -> p.computeIfAbsent( key, mappingFunction ) ); + } + + @Override + public synchronized Object computeIfPresent( Object key, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.computeIfPresent( key, remappingFunction ) ); + } + + @Override + public synchronized Object compute( Object key, BiFunction remappingFunction ) + { + return writeOperation( p -> p.compute( key, remappingFunction ) ); + } + + @Override + public synchronized Object merge( Object key, Object value, + BiFunction remappingFunction ) + { + return writeOperation( p -> p.merge( key, value, remappingFunction ) ); + } + + @Override + public synchronized void load( Reader reader ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void load( InputStream inStream ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void save( OutputStream out, String comments ) + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( Writer writer, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void store( OutputStream out, String comments ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public synchronized void loadFromXML( InputStream in ) throws IOException, InvalidPropertiesFormatException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment ) throws IOException + { + throw new UnsupportedOperationException(); + } + + @Override + public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException + { + throw new UnsupportedOperationException(); + } + +} diff --git a/maven-toolchain-model/src/main/mdo/merger.vm b/maven-toolchain-model/src/main/mdo/merger.vm new file mode 100644 index 000000000000..63c3deab00d1 --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/merger.vm @@ -0,0 +1,358 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.toolchain" ) +#set ( $package = "org.apache.maven.toolchain.v4" ) +#set ( $className = "${model.name}Merger" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.ObjectStreamException; +import java.util.AbstractList; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Iterator; +import java.util.LinkedHashMap; +import java.util.List; +import java.util.Map; +import java.util.Properties; +import java.util.Objects; +import java.util.function.BinaryOperator; +import java.util.function.Function; +import java.util.stream.Collectors; + +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.Name}; +#end + +@Generated +public class ${className} +{ + + /** + * 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 + * null. + * @param source The (read-only) source object that should be merged into the target object, may be + * null. + * @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 null. + */ + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) + { + Objects.requireNonNull( target, "target cannot be null" ); + if ( source == null ) + { + return target; + } + Map context = new HashMap<>(); + if ( hints != null ) + { + context.putAll( hints ); + } + return merge${root.name}( target, source, sourceDominant, context ); + } + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + ${class.name}.Builder builder = ${class.name}.newBuilder( target ); + merge${class.name}( builder, target, source, sourceDominant, context ); + return builder.build(); + } + + protected void merge${class.name}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $class.superClass ) + merge${class.superClass}( builder, target ,source, sourceDominant, context ); + #end + #foreach ( $field in $class.getFields($version) ) + merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); + #end + } + + #foreach ( $field in $allFields ) + #set ( $capField = ${Helper.capitalise($field.name)} ) + protected void merge${class.name}_${capField}( ${class.name}.Builder builder, ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) + { + #if ( $field.type == "String" ) + String src = source.get${capField}(); + String tgt = target.get${capField}(); + if ( src != null && ( sourceDominant || tgt == null ) ) + { + builder.${field.name}( src ); + } + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties src = source.get${capField}(); + if ( src != null ) + { + Properties tgt = target.get${capField}(); + if ( tgt == null ) + { + builder.${field.name}( src ); + } + else + { + Properties merged = new Properties(); + merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); + merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); + builder.${field.name}( merged ); + } + } + #elseif ( $field.to && $field.multiplicity == "1" ) + ${field.to} src = source.get${capField}(); + if ( src != null ) + { + ${field.to} tgt = target.get${capField}(); + if ( tgt == null ) + { + tgt = ${field.to}.newInstance( false ); + } + ${field.to} merged = merge${field.to}( tgt, src, sourceDominant, context ); + if ( merged == src ) + { + builder.${field.name}( merged ); + } + else if ( merged != tgt ) + { + builder.${field.name}( merged ); + } + } + #elseif ( $field.to && $field.multiplicity == "*" ) + builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, get${field.to}Key() ) ); + #elseif ( $field.type == "DOM" ) + Dom src = source.getConfiguration(); + if ( src != null ) + { + Dom tgt = target.getConfiguration(); + if ( tgt == null ) + { + builder.configuration( src ); + } + else if ( sourceDominant ) + { + builder.configuration( src.merge( tgt ) ); + } + else + { + builder.configuration( tgt.merge( src ) ); + } + } + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + + #end +#end + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + protected KeyComputer<${class.name}> get${class.name}Key() + { + return v -> v; + } + #end +#end + + /** + * Use to compute keys for data structures + * @param the data structure type + */ + @FunctionalInterface + public interface KeyComputer extends Function + { + } + + /** + * Merge two lists + */ + public static List merge( List tgt, List src, boolean sourceDominant, KeyComputer computer ) + { + return merge( tgt, src, computer, ( t, s ) -> sourceDominant ? s : t ); + } + + public static List merge( List tgt, List src, KeyComputer computer, BinaryOperator remapping ) + { + if ( src.isEmpty() ) + { + return tgt; + } + + MergingList list; + if ( tgt instanceof MergingList ) + { + list = (MergingList) tgt; + } + else + { + list = new MergingList<>( computer, src.size() + tgt.size() ); + list.mergeAll( tgt, ( t, s ) -> s ); + } + + list.mergeAll( src, remapping ); + return list; + } + + /** + * Merging list + * @param + */ + private static class MergingList extends AbstractList implements java.io.Serializable + { + + private final KeyComputer keyComputer; + private Map map; + private List list; + + MergingList( KeyComputer keyComputer, int initialCapacity ) + { + this.map = new LinkedHashMap<>( initialCapacity ); + this.keyComputer = keyComputer; + } + + Object writeReplace() throws ObjectStreamException + { + return new ArrayList<>( this ); + } + + @Override + public Iterator iterator() + { + if ( map != null ) + { + return map.values().iterator(); + } + else + { + return list.iterator(); + } + } + + void mergeAll( Collection vs, BinaryOperator remapping ) + { + if ( map == null ) + { + map = list.stream().collect( Collectors.toMap( keyComputer, + Function.identity(), + null, + LinkedHashMap::new ) ); + + list = null; + } + + if ( vs instanceof MergingList && ( (MergingList) vs ).map != null ) + { + for ( Map.Entry e : ( (MergingList) vs ).map.entrySet() ) + { + Object key = e.getKey(); + V v = e.getValue(); + map.merge( key, v, remapping ); + } + } + else + { + for ( V v : vs ) + { + Object key = keyComputer.apply( v ); + + map.merge( key, v, remapping ); + } + } + } + + @Override + public boolean contains( Object o ) + { + if ( map != null ) + { + return map.containsValue( o ); + } + else + { + return list.contains( o ); + } + } + + private List asList() + { + if ( list == null ) + { + list = new ArrayList<>( map.values() ); + map = null; + } + return list; + } + + @Override + public void add( int index, V element ) + { + asList().add( index, element ); + } + + @Override + public V remove( int index ) + { + return asList().remove( index ); + } + + @Override + public V get( int index ) + { + return asList().get( index ); + } + + @Override + public int size() + { + if ( map != null ) + { + return map.size(); + } + else + { + return list.size(); + } + } + } +} diff --git a/maven-toolchain-model/src/main/mdo/model-v3.vm b/maven-toolchain-model/src/main/mdo/model-v3.vm new file mode 100644 index 000000000000..bc32573d1fb3 --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/model-v3.vm @@ -0,0 +1,236 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.toolchain.model" ) +#set ( $package = "${basePackage}" ) +#set ( $wrapPackage = "org.apache.maven.api.toolchain" ) +# +#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#REDIRECT ${package.replace('.','/')}/${className}.java + #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) + #foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end + #end + #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #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.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 + ">" ) ) + #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 +package ${package}; + + #foreach ( $imp in $imports ) +import $imp; + #end + +@Generated +public class ${class.name} + #if ( $class.superClass ) + extends ${class.superClass} + #end + implements Serializable, Cloneable +{ + + #if ( ! $class.superClass ) + ${wrapPackage}.${class.name} delegate; + #end + + public ${class.name}() + { + this( ${wrapPackage}.${class.name}.newInstance() ); + } + + public ${class.name}( ${wrapPackage}.${class.name} delegate ) + { + #if ( $class.superClass ) + super( delegate ); + #else + this.delegate = delegate; + #end + } + + public ${class.name} clone() + { + return new ${class.name}( getDelegate() ); + } + + #if ( $class.superClass ) + @Override + #end + public ${wrapPackage}.${class.name} getDelegate() + { + #if ( $class.superClass ) + return ( ${wrapPackage}.${class.name} ) delegate; + #else + return delegate; + #end + } + + #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 ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + { + #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + return new WrapperList<${field.to}, ${wrapPackage}.${field.to}>( + getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), + ${field.to}::new, ${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( 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; + #else + return getDelegate().${pfx}${cap}(); + #end + } + + public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + { + #if ( $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() ); + #else + delegate = getDelegate().with${cap}( ${field.name} ); + #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" ) + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v} ) ) + .collect( Collectors.toList() ) ); + #else + delegate = getDelegate().with${cap}( + Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) + .collect( Collectors.toList() ) ); + #end + } + + #end + #end + public static List<${wrapPackage}.${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<${wrapPackage}.${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/maven-toolchain-model/src/main/mdo/reader.vm b/maven-toolchain-model/src/main/mdo/reader.vm new file mode 100644 index 000000000000..df8ecf62d0c4 --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/reader.vm @@ -0,0 +1,901 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.toolchain" ) +#set ( $package = "org.apache.maven.toolchain.v4" ) +#set ( $className = "${model.name}Xpp3Reader" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +@Generated +public class ${className} +{ + private boolean addDefaultEntities = true; + + private final ContentTransformer contentTransformer; + + public ${className}() + { + this( new ContentTransformer() + { + public String transform( String source, String fieldName ) + { + return source; + } + } ); + } + + public ${className}( ContentTransformer contentTransformer ) + { + this.contentTransformer = contentTransformer; + } + + /** + * Method checkFieldWithDuplicate. + * + * @param parser a parser object. + * @param parsed a parsed object. + * @param alias a alias object. + * @param tagName a tagName object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) + throws XmlPullParserException + { + if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) + { + return false; + } + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + return true; + } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + + /** + * Method checkUnknownAttribute. + * + * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException + { + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) + { + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); + } + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + + /** + * Method checkUnknownElement. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @throws IOException IOException if any. + */ + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException + { + if ( strict ) + { + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) + { + unrecognizedTagCount++; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + unrecognizedTagCount--; + } + } + } //-- void checkUnknownElement( XmlPullParser, boolean ) + + /** + * Returns the state of the "add default entities" flag. + * + * @return boolean + */ + public boolean getAddDefaultEntities() + { + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getBooleanValue. + * + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return boolean + */ + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException + { + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + + /** + * Method getByteValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return byte + */ + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) + { + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) + { + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + } + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } + } + } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + return getIntegerValue( s, attribute, parser, strict, 0 ); + } //-- int getBooleanValue( String, String, XmlPullParser ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return defaultValue; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean, int ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } + } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) + + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + + /** + * Method getTrimmedValue. + * + * @param s a s object. + * @return String + */ + private String getTrimmedValue( String s ) + { + if ( s != null ) + { + s = s.trim(); + } + return s; + } //-- String getTrimmedValue( String ) + + /** + * Method interpolatedTrimmed. + * + * @param value a value object. + * @param context a context object. + * @return String + */ + private String interpolatedTrimmed( String value, String context ) + { + return getTrimmedValue( contentTransformer.transform( value, context ) ); + } //-- String interpolatedTrimmed( String, String ) + + /** + * Method nextTag. + * + * @param parser a parser object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int nextTag( XmlPullParser parser ) + throws IOException, XmlPullParserException + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.TEXT ) + { + eventType = parser.next(); + } + if ( eventType != XmlPullParser.START_TAG && eventType != XmlPullParser.END_TAG ) + { + throw new XmlPullParserException( "expected START_TAG or END_TAG not " + XmlPullParser.TYPES[eventType], parser, null ); + } + return eventType; + } //-- int nextTag( XmlPullParser ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException + { + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- ${root.name} read( Reader, boolean ) + + /** + * @see ReaderFactory#newXmlReader + * + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( Reader reader ) + throws IOException, XmlPullParserException + { + return read( reader, true ); + } //-- ${root.name} read( Reader ) + + /** + * Method read. + * + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- ${root.name} read( InputStream, boolean ) + + /** + * Method read. + * + * @param in a in object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( InputStream in ) + throws IOException, XmlPullParserException + { + return read( ReaderFactory.newXmlReader( in ) ); + } //-- ${root.name} read( InputStream ) + + /** + * Method read. + * + * @param parser a parser object. + * @param strict a strict object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return ${root.name} + */ + public ${root.name} read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + { + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; + } + eventType = parser.next(); + } + if ( parsed ) + { + return $rootLcapName; + } + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- ${root.name} read( XmlPullParser, boolean ) + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException + { + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + { + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) + { + // just ignore attributes with non-default namespace (for example: xmlns:xsi) + } + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) + { + // ignore xmlns attribute in root class, which is a reserved attribute name + } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); + } + } + Set parsed = new HashSet<>(); + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + List<$field.to> ${field.name} = new ArrayList<>(); + #end + #end + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + { + String childName = checkDuplicate( parser.getName(), parser, parsed ); + switch ( childName ) + { + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular( $fieldTagName ) ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" && $Helper.isFlatItems( $field ) ) + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; + } + } + } + #foreach ( $field in $allFields ) + #if ( $Helper.isFlatItems( $field ) ) + ${classLcapName}.${field.name}( ${field.name} ); + #end + #end + return ${classLcapName}.build(); + } + + #end +#end + + private String checkDuplicate( String tagName, XmlPullParser parser, Set parsed ) + throws XmlPullParserException + { +#set( $aliases = { } ) +#set( $flats = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $fieldTagName ) ) + #end + #if ( $Helper.isFlatItems( $field ) ) + #set ( $fieldTagName = $Helper.singular($fieldTagName) ) + #set ( $dummy = $flats.put( $fieldTagName, "" ) ) + #end + #end +#end +#if ( ! ${aliases.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + tagName = "${entry.value}"; + #end + } +#end +#if ( ! ${flats.isEmpty()} ) + switch ( tagName ) + { + #foreach( $entry in $flats.entrySet() ) + case "${entry.key}": + #end + break; + default: + if ( !parsed.add( tagName ) ) + { + throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); + } + } +#end + return tagName; + } + + /** + * Sets the state of the "add default entities" flag. + * + * @param addDefaultEntities a addDefaultEntities object. + */ + public void setAddDefaultEntities( boolean addDefaultEntities ) + { + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) + + public static interface ContentTransformer + { + /** + * Interpolate the value read from the xpp3 document + * @param source The source value + * @param fieldName A description of the field being interpolated. The implementation may use this to + * log stuff. + * @return The interpolated value. + */ + String transform( String source, String fieldName ); + } + +} diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm new file mode 100644 index 000000000000..41ee68060eae --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -0,0 +1,325 @@ +#* + 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. +*# +#set ( $basePackage = "org.apache.maven.api.toolchain" ) +#set ( $package = "org.apache.maven.toolchain.v4" ) +#set ( $className = "${model.name}Xpp3Writer" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) +# +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +package ${package}; + +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; +import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +@Generated +public class ${className} +{ + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${field.defaultValue} == "true" ) + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #else + writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + #end + #elseif ( $field.type == "int" ) + // TODO: name=${field.name} type=${field.type} + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + for ( T t : list ) + { + writer.write( t ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + for ( Map.Entry entry : props.entrySet() ) + { + writeTag( entry.getKey().toString(), null, entry.getValue().toString(), serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + +} diff --git a/maven-xml-impl/pom.xml b/maven-xml-impl/pom.xml new file mode 100644 index 000000000000..b13decef7483 --- /dev/null +++ b/maven-xml-impl/pom.xml @@ -0,0 +1,58 @@ + + + + + + + maven + org.apache.maven + 4.0.0-alpha-1-SNAPSHOT + + 4.0.0 + + maven-xml-impl + + Maven XML Implementation + + + + org.codehaus.plexus + plexus-utils + 3.4.1 + + + org.apache.maven + maven-api-xml + 4.0.0-alpha-1-SNAPSHOT + + + org.apache.maven + maven-api-model + 4.0.0-alpha-1-SNAPSHOT + + + org.eclipse.sisu + org.eclipse.sisu.plexus + + + + diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java new file mode 100644 index 000000000000..4d67730c2803 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java @@ -0,0 +1,93 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.Reader; + +import org.apache.maven.api.model.InputLocation; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +public class DomBuilder +{ + + public static Xpp3Dom build( Reader reader ) + throws MavenXmlException + { + return build( reader, true ); + } + + public static Xpp3Dom build( Reader reader, boolean trim ) + throws MavenXmlException + { + try + { + MXParser parser = new MXParser(); + parser.setInput( reader ); + return build( parser, trim ); + } + catch ( XmlPullParserException e ) + { + throw new MavenXmlException( "Unable to build DOM", e ); + } + } + + public static Xpp3Dom build( XmlPullParser parser ) + { + return build( parser, true, null ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim ) + { + return build( parser, trim, null ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim, LocationBuilder locationBuilder ) + { + try + { + Xpp3DomBuilder.InputLocationBuilder ilb = + locationBuilder != null ? ( p -> locationBuilder.getLocation() ) : null; + return Xpp3DomBuilder.build( parser, trim, ilb ); + } + catch ( Exception e ) + { + throw new MavenXmlException( "Unable to build DOM", e ); + } + } + + public static class LocationBuilder + { + + private final InputLocation location; + + public LocationBuilder( InputLocation location ) + { + this.location = location; + } + + public InputLocation getLocation() + { + return location; + } + } + +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/MavenXmlException.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/MavenXmlException.java new file mode 100644 index 000000000000..7c251eeecd5f --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/MavenXmlException.java @@ -0,0 +1,47 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +public class MavenXmlException extends RuntimeException +{ + public MavenXmlException() + { + } + + public MavenXmlException( String message ) + { + super( message ); + } + + public MavenXmlException( String message, Throwable cause ) + { + super( message, cause ); + } + + public MavenXmlException( Throwable cause ) + { + super( cause ); + } + + public MavenXmlException( String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace ) + { + super( message, cause, enableSuppression, writableStackTrace ); + } +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java new file mode 100644 index 000000000000..ba496a04a88d --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java @@ -0,0 +1,35 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.configuration.DefaultPlexusConfiguration; +import org.codehaus.plexus.configuration.PlexusConfiguration; + +public class XmlPlexusConfiguration +{ + public static PlexusConfiguration toPlexusConfiguration( Dom node ) + { + DefaultPlexusConfiguration dfc = new DefaultPlexusConfiguration( node.getName(), node.getValue() ); + node.getAttributes().forEach( dfc::setAttribute ); + node.getChildren().forEach( c -> dfc.addChild( toPlexusConfiguration( c ) ) ); + return dfc; + } +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java new file mode 100644 index 000000000000..f135f57ed919 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java @@ -0,0 +1,465 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.Serializable; +import java.io.StringWriter; +import java.util.ArrayList; +import java.util.Collections; +import java.util.HashMap; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.Objects; +import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.SerializerXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +/** + * NOTE: remove all the util code in here when separated, this class should be pure data. + */ +public class Xpp3Dom + implements Serializable, Dom +{ + private static final long serialVersionUID = 2567894443061173996L; + + protected final String name; + + protected final String value; + + protected final Map attributes; + + protected final List children; + + protected final Object location; + + + public Xpp3Dom( String name ) + { + this( name, null, null, null, null ); + } + + public Xpp3Dom( String name, String value ) + { + this( name, value, null, null, null ); + } + + public Xpp3Dom( Dom from, String name ) + { + this( name, from.getValue(), from.getAttributes(), + from.getChildren(), from.getInputLocation() ); + } + + public Xpp3Dom( String name, String value, + Map attributes, + List children, + Object location ) + { + this.name = Objects.requireNonNull( name ); + this.value = value; + this.attributes = attributes != null + ? Collections.unmodifiableMap( new HashMap<>( attributes ) ) + : Collections.emptyMap(); + this.children = children != null + ? Collections.unmodifiableList( new ArrayList<>( children ) ) + : Collections.emptyList(); + this.location = location; + } + + @Override + public Dom merge( Dom source, Boolean childMergeOverride ) + { + return merge( this, source, childMergeOverride ); + } + + public Dom clone() + { + return this; + } + + // ---------------------------------------------------------------------- + // Name handling + // ---------------------------------------------------------------------- + + public String getName() + { + return name; + } + + // ---------------------------------------------------------------------- + // Value handling + // ---------------------------------------------------------------------- + + public String getValue() + { + return value; + } + + // ---------------------------------------------------------------------- + // Attribute handling + // ---------------------------------------------------------------------- + + @Override + public Map getAttributes() + { + return attributes; + } + + public String getAttribute( String name ) + { + return attributes.get( name ); + } + + // ---------------------------------------------------------------------- + // Child handling + // ---------------------------------------------------------------------- + + public Dom getChild( String name ) + { + if ( name != null ) + { + ListIterator it = children.listIterator( children.size() ); + while ( it.hasPrevious() ) + { + Dom child = it.previous(); + if ( name.equals( child.getName() ) ) + { + return child; + } + } + } + return null; + } + + public List getChildren() + { + return children; + } + + public int getChildCount() + { + return children.size(); + } + + // ---------------------------------------------------------------------- + // Input location handling + // ---------------------------------------------------------------------- + + /** + * @since 3.2.0 + * @return input location + */ + public Object getInputLocation() + { + return location; + } + + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + + public void writeToSerializer( String namespace, XmlSerializer serializer ) + throws IOException + { + // TODO: WARNING! Later versions of plexus-utils psit out an header due to thinking this is a new + // document - not the desired behaviour! + SerializerXMLWriter xmlWriter = new SerializerXMLWriter( namespace, serializer ); + Xpp3DomWriter.write( xmlWriter, this ); + if ( xmlWriter.getExceptions().size() > 0 ) + { + throw (IOException) xmlWriter.getExceptions().get( 0 ); + } + } + + /** + * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.

+ * The algorithm is as follows: + *

    + *
  1. if the recessive DOM is null, there is nothing to do... return.
  2. + *
  3. Determine whether the dominant node will suppress the recessive one (flag=mergeSelf). + *
      + *
    1. retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'... + * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one + * completely.
    2. + *
    3. otherwise, use the default value for mergeSelf, which is true...this is the same as specifying + * 'combine.self' == 'merge' as an attribute of the dominant root node.
    4. + *
  4. + *
  5. If mergeSelf == true + *
      + *
    1. if the dominant root node's value is empty, set it to the recessive root node's value
    2. + *
    3. For each attribute in the recessive root node which is not set in the dominant root node, set it.
    4. + *
    5. Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as + * siblings (flag=mergeChildren). + *
        + *
      1. if childMergeOverride is set (non-null), use that value (true/false)
      2. + *
      3. retrieve the 'combine.children' attribute on the dominant node, and try to match against + * 'append'...
      4. + *
      5. if it matches 'append', then set mergeChildren == false...the recessive children will be appended as + * siblings of the dominant children.
      6. + *
      7. otherwise, use the default value for mergeChildren, which is true...this is the same as specifying + * 'combine.children' == 'merge' as an attribute on the dominant root node.
      8. + *
    6. + *
    7. Iterate through the recessive children, and: + *
        + *
      1. if mergeChildren == true and there is a corresponding dominant child (matched by element name), + * merge the two.
      2. + *
      3. otherwise, add the recessive child as a new child on the dominant root node.
      4. + *
    8. + *
  6. + *
+ */ + @SuppressWarnings( "checkstyle:MethodLength" ) + public static Dom merge( Dom dominant, Dom recessive, Boolean childMergeOverride ) + { + // TODO: share this as some sort of assembler, implement a walk interface? + if ( recessive == null ) + { + return dominant; + } + if ( dominant == null ) + { + return recessive; + } + + boolean mergeSelf = true; + + String selfMergeMode = dominant.getAttribute( SELF_COMBINATION_MODE_ATTRIBUTE ); + + if ( SELF_COMBINATION_OVERRIDE.equals( selfMergeMode ) ) + { + mergeSelf = false; + } + + if ( mergeSelf ) + { + + String value = null; + Object location = null; + Map attrs = null; + List children = null; + + if ( isEmpty( dominant.getValue() ) && !isEmpty( recessive.getValue() ) ) + { + value = recessive.getValue(); + location = recessive.getInputLocation(); + } + + for ( Map.Entry attr : recessive.getAttributes().entrySet() ) + { + String key = attr.getKey(); + if ( isEmpty( dominant.getAttribute( key ) ) && !SELF_COMBINATION_MODE_ATTRIBUTE.equals( key ) ) + { + if ( attrs == null ) + { + attrs = new HashMap<>(); + } + attrs.put( key, attr.getValue() ); + } + } + + if ( recessive.getChildren().size() > 0 ) + { + boolean mergeChildren = true; + if ( childMergeOverride != null ) + { + mergeChildren = childMergeOverride; + } + else + { + String childMergeMode = dominant.getAttribute( CHILDREN_COMBINATION_MODE_ATTRIBUTE ); + if ( CHILDREN_COMBINATION_APPEND.equals( childMergeMode ) ) + { + mergeChildren = false; + } + } + + if ( !mergeChildren ) + { + children = new ArrayList<>( recessive.getChildren().size() + dominant.getChildren().size() ); + children.addAll( recessive.getChildren() ); + children.addAll( dominant.getChildren() ); + } + else + { + Map> commonChildren = new HashMap<>(); + Set names = recessive.getChildren().stream() + .map( Dom::getName ).collect( Collectors.toSet() ); + for ( String name : names ) + { + List dominantChildren = dominant.getChildren().stream() + .filter( n -> n.getName().equals( name ) ) + .collect( Collectors.toList() ); + if ( dominantChildren.size() > 0 ) + { + commonChildren.put( name, dominantChildren.iterator() ); + } + } + + for ( Dom recessiveChild : recessive.getChildren() ) + { + String name = recessiveChild.getName(); + Iterator it = commonChildren.computeIfAbsent( name, + n1 -> Stream.of( dominant.getChildren().stream() + .filter( n2 -> n2.getName().equals( n1 ) ) + .collect( Collectors.toList() ) ) + .filter( l -> !l.isEmpty() ) + .map( List::iterator ) + .findFirst() + .orElse( null ) ); + if ( it == null ) + { + if ( children == null ) + { + children = new ArrayList<>( dominant.getChildren() ); + } + children.add( recessiveChild ); + } + else if ( it.hasNext() ) + { + Dom dominantChild = it.next(); + + String dominantChildCombinationMode = + dominantChild.getAttribute( SELF_COMBINATION_MODE_ATTRIBUTE ); + if ( SELF_COMBINATION_REMOVE.equals( dominantChildCombinationMode ) ) + { + if ( children == null ) + { + children = new ArrayList<>( dominant.getChildren() ); + } + children.remove( dominantChild ); + } + else + { + int idx = ( children != null ? children : dominant.getChildren() ) + .indexOf( dominantChild ); + Dom merged = merge( dominantChild, recessiveChild, childMergeOverride ); + if ( merged != dominantChild ) + { + if ( children == null ) + { + children = new ArrayList<>( dominant.getChildren() ); + } + children.set( idx, merged ); + } + } + } + } + } + } + + if ( value != null || attrs != null || children != null ) + { + if ( attrs != null ) + { + Map nattrs = attrs; + attrs = new HashMap<>( dominant.getAttributes() ); + attrs.putAll( nattrs ); + } + else + { + attrs = dominant.getAttributes(); + } + if ( children == null ) + { + children = dominant.getChildren(); + } + return new Xpp3Dom( dominant.getName(), value, attrs, children, location ); + } + } + return dominant; + } + + /** + * Merge two DOMs, with one having dominance in the case of collision. Merge mechanisms (vs. override for nodes, or + * vs. append for children) is determined by attributes of the dominant root node. + * + * @see #CHILDREN_COMBINATION_MODE_ATTRIBUTE + * @see #SELF_COMBINATION_MODE_ATTRIBUTE + * @param dominant The dominant DOM into which the recessive value/attributes/children will be merged + * @param recessive The recessive DOM, which will be merged into the dominant DOM + * @return merged DOM + */ + public static Dom merge( Dom dominant, Dom recessive ) + { + return merge( dominant, recessive, null ); + } + + // ---------------------------------------------------------------------- + // Standard object handling + // ---------------------------------------------------------------------- + + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + Xpp3Dom xpp3Dom = (Xpp3Dom) o; + return name.equals( xpp3Dom.name ) && Objects.equals( value, xpp3Dom.value ) && attributes.equals( + xpp3Dom.attributes ) && children.equals( xpp3Dom.children ); + } + + @Override + public int hashCode() + { + return Objects.hash( name, value, attributes, children ); + } + + @Override + public String toString() + { + StringWriter writer = new StringWriter(); + Xpp3DomWriter.write( writer, this ); + return writer.toString(); + } + + public String toUnescapedString() + { + StringWriter writer = new StringWriter(); + XMLWriter xmlWriter = new PrettyPrintXMLWriter( writer ); + Xpp3DomWriter.write( xmlWriter, this, false ); + return writer.toString(); + } + + public static boolean isNotEmpty( String str ) + { + return ( ( str != null ) && ( str.length() > 0 ) ); + } + + public static boolean isEmpty( String str ) + { + return ( ( str == null ) || ( str.trim().length() == 0 ) ); + } + +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomBuilder.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomBuilder.java new file mode 100644 index 000000000000..ee50ab7b4af1 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomBuilder.java @@ -0,0 +1,215 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.IOUtil; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * + */ +public class Xpp3DomBuilder +{ + private static final boolean DEFAULT_TRIM = true; + + public static Xpp3Dom build( Reader reader ) + throws XmlPullParserException, IOException + { + return build( reader, null ); + } + + /** + * @param reader the reader + * @param locationBuilder the builder + * @since 3.2.0 + * @return DOM + * @throws XmlPullParserException xml exception + * @throws IOException io + */ + public static Xpp3Dom build( Reader reader, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return build( reader, DEFAULT_TRIM, locationBuilder ); + } + + public static Xpp3Dom build( InputStream is, String encoding ) + throws XmlPullParserException, IOException + { + return build( is, encoding, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( InputStream is, String encoding, boolean trim ) + throws XmlPullParserException, IOException + { + try + { + final XmlPullParser parser = new MXParser(); + parser.setInput( is, encoding ); + + final Xpp3Dom xpp3Dom = build( parser, trim ); + is.close(); + is = null; + + return xpp3Dom; + } + finally + { + IOUtil.close( is ); + } + } + + public static Xpp3Dom build( Reader reader, boolean trim ) + throws XmlPullParserException, IOException + { + return build( reader, trim, null ); + } + + /** + * @param reader the reader + * @param trim to trim + * @param locationBuilder the builder + * @since 3.2.0 + * @return DOM + * @throws XmlPullParserException xml exception + * @throws IOException io + */ + public static Xpp3Dom build( Reader reader, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + try + { + final XmlPullParser parser = new MXParser(); + parser.setInput( reader ); + + final Xpp3Dom xpp3Dom = build( parser, trim, locationBuilder ); + reader.close(); + reader = null; + + return xpp3Dom; + } + finally + { + IOUtil.close( reader ); + } + } + + public static Xpp3Dom build( XmlPullParser parser ) + throws XmlPullParserException, IOException + { + return build( parser, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim ) + throws XmlPullParserException, IOException + { + return build( parser, trim, null ); + } + + /** + * @since 3.2.0 + * @param locationBuilder builder + * @param parser the parser + * @param trim do trim + * @return DOM + * @throws XmlPullParserException xml exception + * @throws IOException io + */ + public static Xpp3Dom build( XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + boolean spacePreserve = false; + String name = null; + String value = null; + Object location = null; + Map attrs = null; + List children = null; + int eventType = parser.getEventType(); + while ( eventType != XmlPullParser.END_DOCUMENT ) + { + if ( eventType == XmlPullParser.START_TAG ) + { + if ( name == null ) + { + name = parser.getName(); + location = locationBuilder != null ? locationBuilder.toInputLocation( parser ) : null; + int attributesSize = parser.getAttributeCount(); + if ( attributesSize > 0 ) + { + attrs = new HashMap<>(); + for ( int i = 0; i < attributesSize; i++ ) + { + String aname = parser.getAttributeName( i ); + String avalue = parser.getAttributeValue( i ); + attrs.put( aname, avalue ); + spacePreserve = + spacePreserve || ( "xml:space".equals( aname ) && "preserve".equals( avalue ) ); + } + } + } + else + { + if ( children == null ) + { + children = new ArrayList<>(); + } + Dom child = build( parser, trim, locationBuilder ); + children.add( child ); + } + } + else if ( eventType == XmlPullParser.TEXT ) + { + String text = parser.getText(); + if ( trim && !spacePreserve ) + { + text = text.trim(); + } + value = value != null ? value + text : text; + } + else if ( eventType == XmlPullParser.END_TAG ) + { + return new Xpp3Dom( name, children == null ? value : null, + attrs, children, location ); + } + eventType = parser.next(); + } + throw new IllegalStateException( "End of document found before returning to 0 depth" ); + } + + /** + * Input location builder interface, to be implemented to choose how to store data. + * + * @since 3.2.0 + */ + public interface InputLocationBuilder + { + Object toInputLocation( XmlPullParser parser ); + } +} diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomWriter.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomWriter.java new file mode 100644 index 000000000000..7000752ce669 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3DomWriter.java @@ -0,0 +1,79 @@ +package org.apache.maven.internal.xml; + +/* + * 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. + */ + +import java.io.PrintWriter; +import java.io.Writer; +import java.util.Map; + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.PrettyPrintXMLWriter; +import org.codehaus.plexus.util.xml.XMLWriter; + +/** + * + */ +public class Xpp3DomWriter +{ + public static void write( Writer writer, Dom dom ) + { + write( new PrettyPrintXMLWriter( writer ), dom ); + } + + public static void write( PrintWriter writer, Dom dom ) + { + write( new PrettyPrintXMLWriter( writer ), dom ); + } + + public static void write( XMLWriter xmlWriter, Dom dom ) + { + write( xmlWriter, dom, true ); + } + + public static void write( XMLWriter xmlWriter, Dom dom, boolean escape ) + { + // TODO: move to XMLWriter? + xmlWriter.startElement( dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + xmlWriter.addAttribute( attr.getKey(), attr.getValue() ); + } + for ( Dom aChildren : dom.getChildren() ) + { + write( xmlWriter, aChildren, escape ); + } + + String value = dom.getValue(); + if ( value != null ) + { + if ( escape ) + { + xmlWriter.writeText( value ); + } + else + { + xmlWriter.writeMarkup( value ); + } + } + + xmlWriter.endElement(); + } + +} diff --git a/pom.xml b/pom.xml index 7de5d47bc1dd..a0376dae14dd 100644 --- a/pom.xml +++ b/pom.xml @@ -84,6 +84,8 @@ under the License. maven-model maven-model-builder maven-model-transform + api + maven-xml-impl maven-core maven-settings maven-settings-builder @@ -660,7 +662,8 @@ under the License. 3.1.2 info - ${maven.multiModuleProjectDirectory}/build/checkstyle-suppressions.xml + JavadocVariable,JavadocMethod,HiddenField + From 5cb24c2e5e37f9019c8ab102ee437aa5921f9fb4 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 31 Mar 2022 06:44:00 +0200 Subject: [PATCH 02/98] Check value in setter before rebuilding the internal model --- maven-model/src/main/mdo/model-v3.vm | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index ea6daf86ca32..0ab59810920d 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -45,6 +45,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" ) ) @@ -189,14 +190,17 @@ public class ${class.name} public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) { + if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) + { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - delegate = getDelegate().with${cap}( - ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ); + 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() ); + delegate = getDelegate().with${cap}( ${field.name}.getDelegate() ); #else - delegate = getDelegate().with${cap}( ${field.name} ); + delegate = getDelegate().with${cap}( ${field.name} ); #end + } } #if ( $field.type == "java.util.List" && $field.multiplicity == "*" ) From c7ae731c67a2e891ab62468b8689b2fd8c624237 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 31 Mar 2022 11:32:30 +0200 Subject: [PATCH 03/98] Update the module names --- api/maven-api-meta/pom.xml | 2 +- api/maven-api-model/pom.xml | 4 ++-- api/maven-api-settings/pom.xml | 4 ++-- api/maven-api-toolchain/pom.xml | 4 ++-- api/maven-api-xml/pom.xml | 2 +- api/pom.xml | 2 +- 6 files changed, 9 insertions(+), 9 deletions(-) diff --git a/api/maven-api-meta/pom.xml b/api/maven-api-meta/pom.xml index 85e90e3f5ffe..8c4d392ad268 100644 --- a/api/maven-api-meta/pom.xml +++ b/api/maven-api-meta/pom.xml @@ -27,6 +27,6 @@ maven-api-meta - Apache Maven API Meta annotations + Maven API Meta annotations diff --git a/api/maven-api-model/pom.xml b/api/maven-api-model/pom.xml index cd2111693751..ed5b439e7e02 100644 --- a/api/maven-api-model/pom.xml +++ b/api/maven-api-model/pom.xml @@ -30,8 +30,8 @@ under the License. maven-api-model - Maven Model - Model for Maven POM (Project Object Model) + Maven API Model + Maven API Model for Maven POM (Project Object Model) diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml index 4d716baf7e92..93a5abf2c319 100644 --- a/api/maven-api-settings/pom.xml +++ b/api/maven-api-settings/pom.xml @@ -30,8 +30,8 @@ under the License. maven-api-settings - Maven Settings - Maven Settings model. + Maven API Settings + Maven API Settings model. diff --git a/api/maven-api-toolchain/pom.xml b/api/maven-api-toolchain/pom.xml index a179bbcdf621..29dd242e2112 100644 --- a/api/maven-api-toolchain/pom.xml +++ b/api/maven-api-toolchain/pom.xml @@ -31,8 +31,8 @@ under the License. maven-api-toolchain - Maven Toolchain Model - Maven Toolchain model. + Maven API Toolchain + Maven API Toolchain model. diff --git a/api/maven-api-xml/pom.xml b/api/maven-api-xml/pom.xml index 37379006d5c5..42ad25007aeb 100644 --- a/api/maven-api-xml/pom.xml +++ b/api/maven-api-xml/pom.xml @@ -27,7 +27,7 @@ maven-api-xml - Apache Maven API XML + Maven API XML diff --git a/api/pom.xml b/api/pom.xml index 108978e4be01..ce098702c367 100644 --- a/api/pom.xml +++ b/api/pom.xml @@ -27,7 +27,7 @@ maven-api - Apache Maven API + Maven API pom From ad34922b8473f3005036dd8bf5d25637ca7d8d25 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 31 Mar 2022 13:13:24 +0200 Subject: [PATCH 04/98] Fix velocity plugin --- api/maven-api-model/src/main/mdo/maven.mdo | 2 +- api/maven-api-model/src/main/mdo/model.vm | 5 + .../modello/plugin/velocity/Helper.java | 154 ++++++++++++++++++ .../plugin/velocity/ModelloVelocityMojo.java | 52 ++---- .../plugin/velocity/VelocityGenerator.java | 142 ++-------------- maven-model/src/main/mdo/merger.vm | 5 + 6 files changed, 193 insertions(+), 167 deletions(-) create mode 100644 api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/Helper.java diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index 20c72048c809..089ba8432153 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -83,7 +83,7 @@ 5.0.0+ false Originating POM file - java.nio.file.Path + DOM diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index c57c798b7ace..3a64f71abb5d 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -18,6 +18,11 @@ *# #set ( $basePackage = "org.apache.maven.api.model" ) #set ( $package = "${basePackage}" ) +#foreach ( $field in $model.getClass("Model", $version).allFields ) + #if ( $field.name == "pomFile" ) + #set ( $dummy = $field.setType("java.nio.file.Path") ) + #end +#end # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/Helper.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/Helper.java new file mode 100644 index 000000000000..0e9f285fddc7 --- /dev/null +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/Helper.java @@ -0,0 +1,154 @@ +package org.codehaus.modello.plugin.velocity; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Iterator; +import java.util.List; + +import org.codehaus.modello.ModelloRuntimeException; +import org.codehaus.modello.model.ModelAssociation; +import org.codehaus.modello.model.ModelClass; +import org.codehaus.modello.model.ModelField; +import org.codehaus.modello.model.Version; +import org.codehaus.modello.plugin.AbstractModelloGenerator; +import org.codehaus.modello.plugins.xml.metadata.XmlAssociationMetadata; +import org.codehaus.modello.plugins.xml.metadata.XmlClassMetadata; +import org.codehaus.modello.plugins.xml.metadata.XmlFieldMetadata; +import org.codehaus.plexus.util.StringUtils; + +@SuppressWarnings( "unused" ) +public class Helper +{ + private final Version version; + + public Helper( Version version ) + { + this.version = version; + } + + public String capitalise( String str ) + { + return StringUtils.isEmpty( str ) ? str : Character.toTitleCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + public String uncapitalise( String str ) + { + return StringUtils.isEmpty( str ) ? str : Character.toLowerCase( str.charAt( 0 ) ) + str.substring( 1 ); + } + + public String singular( String str ) + { + return AbstractModelloGenerator.singular( str ); + } + + public List ancestors( ModelClass clazz ) + { + List ancestors = new ArrayList<>(); + for ( ModelClass cl = clazz; cl != null; cl = cl.getSuperClass() != null + ? cl.getModel().getClass( cl.getSuperClass(), version ) : null ) + { + ancestors.add( 0, cl ); + } + return ancestors; + } + + public XmlClassMetadata xmlClassMetadata( ModelClass clazz ) + { + return (XmlClassMetadata) clazz.getMetadata( XmlClassMetadata.ID ); + } + + public XmlFieldMetadata xmlFieldMetadata( ModelField field ) + { + return (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); + } + + public XmlAssociationMetadata xmAssociationMetadata( ModelField field ) + { + return (XmlAssociationMetadata) ( (ModelAssociation) field ) + .getAssociationMetadata( XmlAssociationMetadata.ID ); + } + + public boolean isFlatItems( ModelField field ) + { + return field instanceof ModelAssociation && xmAssociationMetadata( field ).isFlatItems(); + } + + public List xmlFields( ModelClass modelClass ) + { + List classes = new ArrayList<>(); + // get the full inheritance + while ( modelClass != null ) + { + classes.add( modelClass ); + String superClass = modelClass.getSuperClass(); + if ( superClass != null ) + { + // superClass can be located outside (not generated by modello) + modelClass = modelClass.getModel().getClass( superClass, version, true ); + } + else + { + modelClass = null; + } + } + List fields = new ArrayList<>(); + for ( int i = classes.size() - 1; i >= 0; i-- ) + { + modelClass = classes.get( i ); + Iterator parentIter = fields.iterator(); + fields = new ArrayList<>(); + for ( ModelField field : modelClass.getFields( version ) ) + { + XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); + if ( xmlFieldMetadata.isTransient() ) + { + // just ignore xml.transient fields + continue; + } + if ( xmlFieldMetadata.getInsertParentFieldsUpTo() != null ) + { + // insert fields from parent up to the specified field + boolean found = false; + while ( !found && parentIter.hasNext() ) + { + ModelField parentField = parentIter.next(); + fields.add( parentField ); + found = parentField.getName().equals( xmlFieldMetadata.getInsertParentFieldsUpTo() ); + } + if ( !found ) + { + // interParentFieldsUpTo not found + throw new ModelloRuntimeException( "parent field not found: class " + + modelClass.getName() + " xml.insertParentFieldUpTo='" + + xmlFieldMetadata.getInsertParentFieldsUpTo() + "'" ); + } + } + fields.add( field ); + } + // add every remaining fields from parent class + while ( parentIter.hasNext() ) + { + fields.add( parentIter.next() ); + } + } + return fields; + } +} diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java index 6e0072e56ef9..3b82a8f5ee8c 100644 --- a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java @@ -20,17 +20,17 @@ */ import java.io.File; -import java.lang.reflect.Field; -import java.lang.reflect.Modifier; +import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.Objects; import java.util.Properties; +import java.util.stream.Collectors; import org.apache.maven.plugins.annotations.LifecyclePhase; import org.apache.maven.plugins.annotations.Mojo; import org.apache.maven.plugins.annotations.Parameter; import org.codehaus.modello.maven.AbstractModelloGeneratorMojo; -import org.codehaus.modello.model.ModelField; /** * Creates an XML schema from the model. @@ -50,6 +50,9 @@ public class ModelloVelocityMojo @Parameter private List templates; + @Parameter + private List params; + protected String getGeneratorType() { return "velocity"; @@ -57,40 +60,15 @@ protected String getGeneratorType() protected void customizeParameters( Properties parameters ) { - try - { - Field field = ModelField.class.getDeclaredField( "PRIMITIVE_TYPES" ); - field.setAccessible( true ); - unsetFinal( field ); - field.set( null, new String[] { "boolean", "Boolean", "char", "Character", "byte", - "Byte", "short", "Short", "int", "Integer", "long", "Long", "float", "Float", - "double", "Double", "String", "Date", "DOM", "java.nio.file.Path" } ); - - super.customizeParameters( parameters ); - parameters.put( "basedir", Objects.requireNonNull( getBasedir(), "basedir is null" ) ); - parameters.put( VelocityGenerator.VELOCITY_TEMPLATES, String.join( ",", templates ) ); - } - catch ( Throwable e ) - { - throw new RuntimeException( e ); - } - } - - private void unsetFinal( Field field ) throws IllegalAccessException, NoSuchFieldException - { -// TODO: on jdk >= 12, accessing Field.modifiers fail, need to check with VarHandle or adds an open module -// try -// { - Field modifiersField = Field.class.getDeclaredField( "modifiers" ); - modifiersField.setAccessible( true ); - modifiersField.setInt( field, field.getModifiers() & ~Modifier.FINAL ); -// } -// catch ( Throwable t ) -// { -// MethodHandles.Lookup lookup = MethodHandles.privateLookupIn(Field.class, MethodHandles.lookup()); -// VarHandle modifiers = lookup.findVarHandle( Field.class, "modifiers", int.class ); -// modifiers.set( field, field.getModifiers() & ~Modifier.FINAL ); -// } + super.customizeParameters( parameters ); + Map params = this.params != null ? this.params.stream().collect( Collectors.toMap( + s -> s.substring( 0, s.indexOf( '=' ) ), s -> s.substring( s.indexOf( '=' ) + 1 ) + ) ) : Collections.emptyMap(); + getLog().warn( "templates: " + templates ); + getLog().warn( "params: " + params ); + parameters.put( "basedir", Objects.requireNonNull( getBasedir(), "basedir is null" ) ); + parameters.put( VelocityGenerator.VELOCITY_TEMPLATES, String.join( ",", templates ) ); + parameters.put( VelocityGenerator.VELOCITY_PARAMETERS, params ); } protected boolean producesCompilableResult() diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java index 95677021ce03..2c0c999d787d 100644 --- a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java @@ -25,10 +25,8 @@ import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; -import java.util.ArrayList; -import java.util.Iterator; -import java.util.List; import java.util.Map; +import java.util.Objects; import java.util.Properties; import org.apache.velocity.Template; @@ -36,19 +34,11 @@ import org.apache.velocity.runtime.RuntimeInstance; import org.codehaus.modello.ModelloException; import org.codehaus.modello.ModelloParameterConstants; -import org.codehaus.modello.ModelloRuntimeException; import org.codehaus.modello.model.Model; -import org.codehaus.modello.model.ModelAssociation; -import org.codehaus.modello.model.ModelClass; -import org.codehaus.modello.model.ModelField; import org.codehaus.modello.model.Version; import org.codehaus.modello.plugin.AbstractModelloGenerator; import org.codehaus.modello.plugin.ModelloGenerator; -import org.codehaus.modello.plugins.xml.metadata.XmlAssociationMetadata; -import org.codehaus.modello.plugins.xml.metadata.XmlClassMetadata; -import org.codehaus.modello.plugins.xml.metadata.XmlFieldMetadata; import org.codehaus.plexus.component.annotations.Component; -import org.codehaus.plexus.util.StringUtils; @Component( role = ModelloGenerator.class, hint = "velocity" ) public class VelocityGenerator @@ -56,11 +46,14 @@ public class VelocityGenerator { public static final String VELOCITY_TEMPLATES = "modello.velocity.template"; + public static final String VELOCITY_PARAMETERS = "modello.velocity.parameters"; + @Override public void generate( Model model, Properties parameters ) throws ModelloException { try { + Map params = ( Map ) Objects.requireNonNull( parameters.get( VELOCITY_PARAMETERS ) ); String templates = getParameter( parameters, VELOCITY_TEMPLATES ); String output = getParameter( parameters, ModelloParameterConstants.OUTPUT_DIRECTORY ); @@ -74,11 +67,20 @@ public void generate( Model model, Properties parameters ) throws ModelloExcepti { context.put( prop.getKey().toString(), prop.getValue() ); } + for ( Map.Entry prop : params.entrySet() ) + { + context.put( prop.getKey(), prop.getValue() ); + } Version version = new Version( getParameter( parameters, ModelloParameterConstants.VERSION ) ); context.put( "version", version ); context.put( "model", model ); context.put( "Helper", new Helper( version ) ); + for ( String key : context.getKeys() ) + { + getLogger().warn( "context: " + key + " -> " + context.get( key ) ); + } + for ( String templatePath : templates.split( "," ) ) { Template template = velocity.getTemplate( templatePath ); @@ -96,124 +98,6 @@ public void generate( Model model, Properties parameters ) throws ModelloExcepti } - public static class Helper - { - private final Version version; - - public Helper( Version version ) - { - this.version = version; - } - - public String capitalise( String str ) - { - return StringUtils.isEmpty( str ) ? str : Character.toTitleCase( str.charAt( 0 ) ) + str.substring( 1 ); - } - - public String uncapitalise( String str ) - { - return StringUtils.isEmpty( str ) ? str : Character.toLowerCase( str.charAt( 0 ) ) + str.substring( 1 ); - } - - public String singular( String str ) - { - return AbstractModelloGenerator.singular( str ); - } - - public List ancestors( ModelClass clazz ) - { - List ancestors = new ArrayList<>(); - for ( ModelClass cl = clazz; cl != null; cl = cl.getSuperClass() != null - ? cl.getModel().getClass( cl.getSuperClass(), version ) : null ) - { - ancestors.add( 0, cl ); - } - return ancestors; - } - - public XmlClassMetadata xmlClassMetadata( ModelClass clazz ) - { - return (XmlClassMetadata) clazz.getMetadata( XmlClassMetadata.ID ); - } - - public XmlFieldMetadata xmlFieldMetadata( ModelField field ) - { - return (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); - } - - public XmlAssociationMetadata xmAssociationMetadata( ModelField field ) - { - return (XmlAssociationMetadata) ( ( ModelAssociation ) field ) - .getAssociationMetadata( XmlAssociationMetadata.ID ); - } - - public boolean isFlatItems( ModelField field ) - { - return field instanceof ModelAssociation && xmAssociationMetadata( field ).isFlatItems(); - } - - public List xmlFields( ModelClass modelClass ) - { - List classes = new ArrayList<>(); - // get the full inheritance - while ( modelClass != null ) - { - classes.add( modelClass ); - String superClass = modelClass.getSuperClass(); - if ( superClass != null ) - { - // superClass can be located outside (not generated by modello) - modelClass = modelClass.getModel().getClass( superClass, version, true ); - } - else - { - modelClass = null; - } - } - List fields = new ArrayList<>(); - for ( int i = classes.size() - 1; i >= 0; i-- ) - { - modelClass = classes.get( i ); - Iterator parentIter = fields.iterator(); - fields = new ArrayList<>(); - for ( ModelField field : modelClass.getFields( version ) ) - { - XmlFieldMetadata xmlFieldMetadata = (XmlFieldMetadata) field.getMetadata( XmlFieldMetadata.ID ); - if ( xmlFieldMetadata.isTransient() ) - { - // just ignore xml.transient fields - continue; - } - if ( xmlFieldMetadata.getInsertParentFieldsUpTo() != null ) - { - // insert fields from parent up to the specified field - boolean found = false; - while ( !found && parentIter.hasNext() ) - { - ModelField parentField = parentIter.next(); - fields.add( parentField ); - found = parentField.getName().equals( xmlFieldMetadata.getInsertParentFieldsUpTo() ); - } - if ( !found ) - { - // interParentFieldsUpTo not found - throw new ModelloRuntimeException( "parent field not found: class " - + modelClass.getName() + " xml.insertParentFieldUpTo='" - + xmlFieldMetadata.getInsertParentFieldsUpTo() + "'" ); - } - } - fields.add( field ); - } - // add every remaining fields from parent class - while ( parentIter.hasNext() ) - { - fields.add( parentIter.next() ); - } - } - return fields; - } - } - static class RedirectingWriter extends Writer { Path dir; diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm index 9a9d972e9765..7b2a78f8639c 100644 --- a/maven-model/src/main/mdo/merger.vm +++ b/maven-model/src/main/mdo/merger.vm @@ -19,6 +19,11 @@ #set ( $basePackage = "org.apache.maven.api.model" ) #set ( $package = "org.apache.maven.model.v4" ) #set ( $className = "ModelMerger" ) +#foreach ( $field in $model.getClass("Model", $version).allFields ) + #if ( $field.name == "pomFile" ) + #set ( $dummy = $field.setType("java.nio.file.Path") ) + #end +#end # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java package ${package}; From 941a23367a76443fc2c5496ac393209d0e19dd61 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 31 Mar 2022 14:36:35 +0200 Subject: [PATCH 05/98] Add a with() method in the model classes --- api/maven-api-model/src/main/mdo/model.vm | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 3a64f71abb5d..97227ab26ced 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -230,12 +230,16 @@ public class ${class.name} #end } + public Builder with() + { + return newBuilder( this ); + } #foreach ( $field in $allFields ) #set ( $cap = $Helper.capitalise( $field.name ) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) public ${class.name} with${cap}( $type $field.name ) { - return newBuilder( this ).${field.name}( $field.name ).build(); + return with().${field.name}( $field.name ).build(); } #end From 0663fae15f20690df43655d79573ff6d8095228f Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 31 Mar 2022 19:52:34 +0200 Subject: [PATCH 06/98] Fix a few ITs --- .../model/building/DefaultModelBuilder.java | 84 +++++++++++-------- .../building/DefaultModelBuilderFactory.java | 13 ++- .../AbstractStringBasedModelInterpolator.java | 9 +- .../StringVisitorModelInterpolator.java | 5 +- .../DefaultPluginConfigurationExpander.java | 8 -- .../StringVisitorModelInterpolatorTest.java | 2 +- .../org/apache/maven/model/InputLocation.java | 3 +- .../apache/maven/internal/xml/Xpp3Dom.java | 3 +- 8 files changed, 68 insertions(+), 59 deletions(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 1f51c7f924db..22055d351fa3 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -33,7 +33,6 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; -import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -66,6 +65,7 @@ import org.apache.maven.model.composition.DependencyManagementImporter; import org.apache.maven.model.inheritance.InheritanceAssembler; import org.apache.maven.model.interpolation.ModelInterpolator; +import org.apache.maven.model.interpolation.ModelVersionProcessor; import org.apache.maven.model.io.ModelParseException; import org.apache.maven.model.io.ModelReader; import org.apache.maven.model.management.DependencyManagementInjector; @@ -126,6 +126,7 @@ public class DefaultModelBuilder private final ReportConfigurationExpander reportConfigurationExpander; private final ReportingConverter reportingConverter; private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator; + private final ModelVersionProcessor versionProcessor; @Inject public DefaultModelBuilder( @@ -146,7 +147,8 @@ public DefaultModelBuilder( PluginConfigurationExpander pluginConfigurationExpander, ReportConfigurationExpander reportConfigurationExpander, ReportingConverter reportingConverter, - ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator ) + ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator, + ModelVersionProcessor versionProcessor ) { this.modelProcessor = modelProcessor; this.modelValidator = modelValidator; @@ -166,6 +168,7 @@ public DefaultModelBuilder( this.reportConfigurationExpander = reportConfigurationExpander; this.reportingConverter = reportingConverter; this.profileActivationFilePathInterpolator = profileActivationFilePathInterpolator; + this.versionProcessor = versionProcessor; } /** @@ -179,7 +182,7 @@ public DefaultModelBuilder setModelProcessor( ModelProcessor modelProcessor ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -193,7 +196,7 @@ public DefaultModelBuilder setModelValidator( ModelValidator modelValidator ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -207,7 +210,7 @@ public DefaultModelBuilder setModelNormalizer( ModelNormalizer modelNormalizer ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -221,7 +224,7 @@ public DefaultModelBuilder setModelInterpolator( ModelInterpolator modelInterpol modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -235,7 +238,7 @@ public DefaultModelBuilder setModelPathTranslator( ModelPathTranslator modelPath modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -249,7 +252,7 @@ public DefaultModelBuilder setModelUrlNormalizer( ModelUrlNormalizer modelUrlNor modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -263,7 +266,7 @@ public DefaultModelBuilder setSuperPomProvider( SuperPomProvider superPomProvide modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -277,7 +280,7 @@ public DefaultModelBuilder setInheritanceAssembler( InheritanceAssembler inherit modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -291,7 +294,7 @@ public DefaultModelBuilder setProfileSelector( ProfileSelector profileSelector ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -305,7 +308,7 @@ public DefaultModelBuilder setProfileInjector( ProfileInjector profileInjector ) modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -319,7 +322,7 @@ public DefaultModelBuilder setPluginManagementInjector( PluginManagementInjector modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -334,7 +337,7 @@ public DefaultModelBuilder setDependencyManagementInjector( modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -349,7 +352,7 @@ public DefaultModelBuilder setDependencyManagementImporter( modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -363,7 +366,7 @@ public DefaultModelBuilder setLifecycleBindingsInjector( LifecycleBindingsInject modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -377,7 +380,7 @@ public DefaultModelBuilder setPluginConfigurationExpander( PluginConfigurationEx modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -391,7 +394,7 @@ public DefaultModelBuilder setReportConfigurationExpander( ReportConfigurationEx modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -405,7 +408,7 @@ public DefaultModelBuilder setReportingConverter( ReportingConverter reportingCo modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } /** @@ -420,7 +423,7 @@ public DefaultModelBuilder setProfileActivationFilePathInterpolator( modelPathTranslator, modelUrlNormalizer, superPomProvider, inheritanceAssembler, profileSelector, profileInjector, pluginManagementInjector, dependencyManagementInjector, dependencyManagementImporter, lifecycleBindingsInjector, pluginConfigurationExpander, reportConfigurationExpander, - reportingConverter, profileActivationFilePathInterpolator ); + reportingConverter, profileActivationFilePathInterpolator, versionProcessor ); } @Override @@ -1200,6 +1203,16 @@ private Model interpolateModel( Model model, ModelBuildingRequest request, Model // save profile activations before interpolation, since they are evaluated with limited scope Map originalActivations = getProfileActivations( model ); + // Overwrite existing values in model properties. Otherwise it's not possible + // to define the version via command line: mvn -Drevision=6.5.7 ... + Properties props = new Properties(); + props.putAll( model.getProperties() ); + versionProcessor.overwriteModelProperties( props, request ); + if ( !props.equals( model.getProperties() ) ) + { + model = model.withProperties( props ); + } + Path projectDir = model.getProjectDirectory(); Model interpolatedModel = modelInterpolator.interpolateModel( model, projectDir != null ? projectDir.toFile() : null, request, problems ); @@ -1545,10 +1558,8 @@ private Model importDependencyManagement( Model model, ModelBuildingRequest requ List newDependencies = null; - for ( Iterator it = depMgmt.getDependencies().iterator(); it.hasNext(); ) + for ( Dependency dependency : depMgmt.getDependencies() ) { - Dependency dependency = it.next(); - if ( !"pom".equals( dependency.getType() ) || !"import".equals( dependency.getScope() ) ) { continue; @@ -1560,8 +1571,17 @@ private Model importDependencyManagement( Model model, ModelBuildingRequest requ } newDependencies.remove( dependency ); + AtomicReference resolvedDependency = new AtomicReference<>(); + DependencyManagement importMgmt = loadDependencyManagement( model, request, problems, - dependency, importIds ); + dependency, importIds, resolvedDependency ); + + if ( resolvedDependency.get() != null ) + { + // TODO: The dependency for the BOM has been resolved, but we are actually getting rid of it... + // Before the introduction of the immutable model, the dependency was updated. + Dependency resolvedDep = resolvedDependency.get(); + } if ( importMgmt != null ) { @@ -1587,7 +1607,8 @@ private Model importDependencyManagement( Model model, ModelBuildingRequest requ private DependencyManagement loadDependencyManagement( Model model, ModelBuildingRequest request, DefaultModelProblemCollector problems, Dependency dependency, - Collection importIds ) + Collection importIds, + AtomicReference resolvedDependency ) { String groupId = dependency.getGroupId(); String artifactId = dependency.getArtifactId(); @@ -1640,7 +1661,7 @@ private DependencyManagement loadDependencyManagement( Model model, ModelBuildin if ( importMgmt == null ) { importMgmt = doLoadDependencyManagement( model, request, problems, dependency, - groupId, artifactId, version, importIds ); + groupId, artifactId, version, importIds, resolvedDependency ); if ( importMgmt != null ) { intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt ); @@ -1657,7 +1678,8 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild String groupId, String artifactId, String version, - Collection importIds ) + Collection importIds, + AtomicReference resolvedDependency ) { DependencyManagement importMgmt; final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver(); @@ -1689,10 +1711,9 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild if ( importModel == null ) { final ModelSource importSource; - final AtomicReference modified = new AtomicReference<>(); try { - importSource = modelResolver.resolveModel( dependency, modified ); + importSource = modelResolver.resolveModel( dependency, resolvedDependency ); } catch ( UnresolvableModelException e ) { @@ -1710,11 +1731,6 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild return null; } - if ( modified.get() != null ) - { - throw new UnsupportedOperationException( "NEED TO UPDATE DEPENDENCY" ); - } - final ModelBuildingResult importResult; try { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java index 02764d052d80..5d0a159f2845 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java @@ -101,6 +101,7 @@ public class DefaultModelBuilderFactory private ReportConfigurationExpander reportConfigurationExpander; private ReportingConverter reportingConverter; private ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator; + private ModelVersionProcessor versionProcessor; public DefaultModelBuilderFactory setModelProcessor( ModelProcessor modelProcessor ) { @@ -216,6 +217,12 @@ public DefaultModelBuilderFactory setProfileActivationFilePathInterpolator( return this; } + public DefaultModelBuilderFactory setVersionProcessor( ModelVersionProcessor versionProcessor ) + { + this.versionProcessor = versionProcessor; + return this; + } + protected ModelProcessor newModelProcessor() { return new DefaultModelProcessor( newModelLocator(), newModelReader() ); @@ -261,8 +268,7 @@ protected ModelInterpolator newModelInterpolator() { UrlNormalizer normalizer = newUrlNormalizer(); PathTranslator pathTranslator = newPathTranslator(); - ModelVersionProcessor versionProcessor = newModelVersionPropertiesProcessor(); - return new StringVisitorModelInterpolator( pathTranslator, normalizer, versionProcessor ); + return new StringVisitorModelInterpolator( pathTranslator, normalizer ); } protected ModelVersionProcessor newModelVersionPropertiesProcessor() @@ -372,7 +378,8 @@ public DefaultModelBuilder newInstance() reportConfigurationExpander != null ? reportConfigurationExpander : newReportConfigurationExpander(), reportingConverter != null ? reportingConverter : newReportingConverter(), profileActivationFilePathInterpolator != null - ? profileActivationFilePathInterpolator : newProfileActivationFilePathInterpolator() + ? profileActivationFilePathInterpolator : newProfileActivationFilePathInterpolator(), + versionProcessor != null ? versionProcessor : newModelVersionPropertiesProcessor() ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java index d25513edff7b..82e27cb88b9d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java @@ -78,15 +78,12 @@ public abstract class AbstractStringBasedModelInterpolator private final PathTranslator pathTranslator; private final UrlNormalizer urlNormalizer; - private final ModelVersionProcessor versionProcessor; @Inject - public AbstractStringBasedModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer, - ModelVersionProcessor processor ) + public AbstractStringBasedModelInterpolator( PathTranslator pathTranslator, UrlNormalizer urlNormalizer ) { this.pathTranslator = pathTranslator; this.urlNormalizer = urlNormalizer; - this.versionProcessor = processor; } protected List createValueSources( final Model model, final File projectDir, @@ -142,10 +139,6 @@ public Object getValue( String expression ) valueSources.add( new MapBasedValueSource( config.getUserProperties() ) ); - // Overwrite existing values in model properties. Otherwise it's not possible - // to define the version via command line: mvn -Drevision=6.5.7 ... - versionProcessor.overwriteModelProperties( modelProperties, config ); - valueSources.add( new MapBasedValueSource( modelProperties ) ); valueSources.add( new MapBasedValueSource( config.getSystemProperties() ) ); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java index 5bba995fd1b7..4e53db546f99 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java @@ -55,10 +55,9 @@ public class StringVisitorModelInterpolator { @Inject public StringVisitorModelInterpolator( PathTranslator pathTranslator, - UrlNormalizer urlNormalizer, - ModelVersionProcessor processor ) + UrlNormalizer urlNormalizer ) { - super( pathTranslator, urlNormalizer, processor ); + super( pathTranslator, urlNormalizer ); } interface InnerInterpolator diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java index ba88dd19d7b1..3395234fb1cf 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java @@ -83,14 +83,6 @@ private List expand( List plugins ) for ( PluginExecution execution : plugin.getExecutions() ) { Dom childDom = execution.getConfiguration(); - if ( childDom != null ) - { - childDom.merge( parentDom ); - } - else - { - childDom = parentDom.clone(); - } executions.add( execution.withConfiguration( childDom != null ? childDom.merge( parentDom ) : parentDom ) ); } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java index 8fa92cecf9b7..e4b11cca8c35 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolatorTest.java @@ -23,6 +23,6 @@ public class StringVisitorModelInterpolatorTest extends AbstractModelInterpolato { protected ModelInterpolator createInterpolator() { - return new StringVisitorModelInterpolator( null, null, new DefaultModelVersionProcessor() ); + return new StringVisitorModelInterpolator( null, null ); } } \ No newline at end of file diff --git a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java index c4bca7817489..6b6ba9d9266e 100644 --- a/maven-model/src/main/java/org/apache/maven/model/InputLocation.java +++ b/maven-model/src/main/java/org/apache/maven/model/InputLocation.java @@ -74,7 +74,8 @@ public InputLocation( org.apache.maven.api.model.InputLocation location ) this.source = location.getSource() != null ? new InputSource( location.getSource() ) : null; this.locations = location.getLocations().isEmpty() ? null : location.getLocations().entrySet().stream().collect( - Collectors.toMap( e -> e.getKey(), e -> new InputLocation( e.getValue() ) ) ); + Collectors.toMap( e -> e.getKey(), + e -> e.getValue() == location ? this : new InputLocation( e.getValue() ) ) ); } public InputLocation( int lineNumber, int columnNumber) diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java index f135f57ed919..05f7e597a764 100644 --- a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/Xpp3Dom.java @@ -388,7 +388,8 @@ else if ( it.hasNext() ) { children = dominant.getChildren(); } - return new Xpp3Dom( dominant.getName(), value, attrs, children, location ); + return new Xpp3Dom( dominant.getName(), value != null ? value : dominant.getValue(), + attrs, children, location ); } } return dominant; From 5052784fe4816c3f8d65971c789efcbb092508a3 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Apr 2022 09:17:23 +0200 Subject: [PATCH 07/98] Fix plexus dom support --- .../DefaultMojoExecutionConfigurator.java | 4 +- .../CanonicalProjectBuilderTest.java | 4 +- .../harness/Xpp3DomPointerFactory.java | 8 + maven-model/src/main/mdo/model-v3.vm | 20 +- maven-xml-impl/pom.xml | 10 +- .../org/codehaus/plexus/util/xml/Xpp3Dom.java | 446 ++++++++++++++++++ .../plexus/util/xml/Xpp3DomBuilder.java | 110 +++++ 7 files changed, 588 insertions(+), 14 deletions(-) create mode 100644 maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java create mode 100644 maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java index 3899a0d9eea2..3ac861311d70 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java @@ -65,11 +65,11 @@ public void configure( MavenProject project, MojoExecution mojoExecution, boolea if ( pluginExecution != null ) { - pomConfiguration = pluginExecution.getConfiguration(); + pomConfiguration = pluginExecution.getDelegate().getConfiguration(); } else if ( allowPluginLevelConfig ) { - pomConfiguration = plugin.getConfiguration(); + pomConfiguration = plugin.getDelegate().getConfiguration(); } Dom mojoConfiguration = Xpp3Dom.merge( mojoExecution.getConfiguration(), pomConfiguration ); diff --git a/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java b/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java index 687cb7d160cf..8330c3c294f4 100644 --- a/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java +++ b/maven-core/src/test/java/org/apache/maven/project/canonical/CanonicalProjectBuilderTest.java @@ -77,7 +77,7 @@ public void testProjectBuilder() assertEquals( "1.0", plugin.getVersion() ); - Dom configuration = plugin.getConfiguration(); + Dom configuration = plugin.getDelegate().getConfiguration(); assertEquals( "src/conf/plexus.conf", configuration.getChild( "plexusConfiguration" ).getValue() ); @@ -98,7 +98,7 @@ public void testProjectBuilder() assertEquals( "plexus:runtime", g0 ); - configuration = execution.getConfiguration(); + configuration = execution.getDelegate().getConfiguration(); assertEquals( "ContinuumPro", configuration.getChild( "plexusApplicationName" ).getValue() ); diff --git a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java index f2a686a2bcbf..24aab57dcc68 100644 --- a/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java +++ b/maven-core/src/test/java/org/apache/maven/project/harness/Xpp3DomPointerFactory.java @@ -42,6 +42,10 @@ public int getOrder() public NodePointer createNodePointer( QName name, Object object, Locale locale ) { + if ( object instanceof org.codehaus.plexus.util.xml.Xpp3Dom ) + { + object = ( ( org.codehaus.plexus.util.xml.Xpp3Dom ) object ).getDom(); + } if ( object instanceof Dom ) { return new Xpp3DomNodePointer( (Dom) object ); @@ -51,6 +55,10 @@ public NodePointer createNodePointer( QName name, Object object, Locale locale ) public NodePointer createNodePointer( NodePointer parent, QName name, Object object ) { + if ( object instanceof org.codehaus.plexus.util.xml.Xpp3Dom ) + { + object = ( ( org.codehaus.plexus.util.xml.Xpp3Dom ) object ).getDom(); + } if ( object instanceof Dom ) { return new Xpp3DomNodePointer( parent, (Dom) object ); diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 0ab59810920d..9b972015aead 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -37,7 +37,7 @@ #set ( $root = $class ) #end #end - #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $types = { "DOM": "Object" } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) #set ( $dummy = $imports.add( "java.util.AbstractList" ) ) @@ -183,6 +183,8 @@ public class ${class.name} return new WrapperList( 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; + #elseif ( $field.type == "DOM" ) + return getDelegate().${pfx}${cap}() != null ? new org.codehaus.plexus.util.xml.Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; #else return getDelegate().${pfx}${cap}(); #end @@ -190,17 +192,25 @@ public class ${class.name} public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) { + #if ( $field.type == "DOM" ) + org.codehaus.plexus.util.xml.Xpp3Dom dom = ( org.codehaus.plexus.util.xml.Xpp3Dom ) ${field.name}; + if ( ! Objects.equals( dom != null ? dom.getDom() : null, getDelegate().${pfx}${cap}() ) ) + { + delegate = getDelegate().with${cap}( dom.getDom() ); + } + #else if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) { - #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) + #if ( $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" ) + #elseif ( $field.to && $field.to != "String" ) delegate = getDelegate().with${cap}( ${field.name}.getDelegate() ); - #else + #else delegate = getDelegate().with${cap}( ${field.name} ); - #end + #end } + #end } #if ( $field.type == "java.util.List" && $field.multiplicity == "*" ) diff --git a/maven-xml-impl/pom.xml b/maven-xml-impl/pom.xml index b13decef7483..04e7c53af33b 100644 --- a/maven-xml-impl/pom.xml +++ b/maven-xml-impl/pom.xml @@ -34,11 +34,6 @@ under the License. Maven XML Implementation - - org.codehaus.plexus - plexus-utils - 3.4.1 - org.apache.maven maven-api-xml @@ -53,6 +48,11 @@ under the License. org.eclipse.sisu org.eclipse.sisu.plexus + + org.codehaus.plexus + plexus-utils + 3.4.1 + diff --git a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java new file mode 100644 index 000000000000..bf82963a955f --- /dev/null +++ b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java @@ -0,0 +1,446 @@ +package org.codehaus.plexus.util.xml; + +/* + * 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. + */ + +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; + +import java.io.IOException; +import java.io.Serializable; +import java.util.ArrayList; +import java.util.HashMap; +import java.util.List; +import java.util.Map; + +/** + * NOTE: remove all the util code in here when separated, this class should be pure data. + */ +public class Xpp3Dom + implements Serializable +{ + private static final String[] EMPTY_STRING_ARRAY = new String[0]; + + private static final Xpp3Dom[] EMPTY_DOM_ARRAY = new Xpp3Dom[0]; + + public static final String CHILDREN_COMBINATION_MODE_ATTRIBUTE = "combine.children"; + + public static final String CHILDREN_COMBINATION_MERGE = "merge"; + + public static final String CHILDREN_COMBINATION_APPEND = "append"; + + /** + * This default mode for combining children DOMs during merge means that where element names match, the process will + * try to merge the element data, rather than putting the dominant and recessive elements (which share the same + * element name) as siblings in the resulting DOM. + */ + public static final String DEFAULT_CHILDREN_COMBINATION_MODE = CHILDREN_COMBINATION_MERGE; + + public static final String SELF_COMBINATION_MODE_ATTRIBUTE = "combine.self"; + + public static final String SELF_COMBINATION_OVERRIDE = "override"; + + public static final String SELF_COMBINATION_MERGE = "merge"; + + public static final String SELF_COMBINATION_REMOVE = "remove"; + + /** + * This default mode for combining a DOM node during merge means that where element names match, the process will + * try to merge the element attributes and values, rather than overriding the recessive element completely with the + * dominant one. This means that wherever the dominant element doesn't provide the value or a particular attribute, + * that value or attribute will be set from the recessive DOM node. + */ + public static final String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE; + + private Dom dom; + + public Xpp3Dom( String name ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( name ); + } + + /** + * @since 3.2.0 + * @param inputLocation The input location. + * @param name The name of the Dom. + */ + public Xpp3Dom( String name, Object inputLocation ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( name, null, null, null, inputLocation ); + } + + /** + * Copy constructor. + * @param src The source Dom. + */ + public Xpp3Dom( Xpp3Dom src ) + { + this( src, src.getName() ); + } + + /** + * Copy constructor with alternative name. + * @param src The source Dom. + * @param name The name of the Dom. + */ + public Xpp3Dom( Xpp3Dom src, String name ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( src.dom, name ); + } + + public Xpp3Dom( Dom dom ) + { + this.dom = dom; + } + + public Dom getDom() + { + return dom; + } + + // ---------------------------------------------------------------------- + // Name handling + // ---------------------------------------------------------------------- + + public String getName() + { + return dom.getName(); + } + + // ---------------------------------------------------------------------- + // Value handling + // ---------------------------------------------------------------------- + + public String getValue() + { + return dom.getValue(); + } + + public void setValue( String value ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), value, dom.getAttributes(), dom.getChildren(), dom.getInputLocation() ); + } + + // ---------------------------------------------------------------------- + // Attribute handling + // ---------------------------------------------------------------------- + + public String[] getAttributeNames() + { + return dom.getAttributes().keySet().toArray( EMPTY_STRING_ARRAY ); + } + + public String getAttribute( String name ) + { + return dom.getAttribute( name ); + } + + /** + * + * @param name name of the attribute to be removed + * @return true if the attribute has been removed + * @since 3.4.0 + */ + public boolean removeAttribute( String name ) + { + if ( ! StringUtils.isEmpty( name ) ) + { + Map attrs = new HashMap<>( dom.getAttributes() ); + boolean ret = attrs.remove( name ) != null; + if ( ret ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ); + } + return ret; + } + return false; + } + + /** + * Set the attribute value + * + * @param name String not null + * @param value String not null + */ + public void setAttribute( String name, String value ) + { + if ( null == value ) + { + throw new NullPointerException( "Attribute value can not be null" ); + } + if ( null == name ) + { + throw new NullPointerException( "Attribute name can not be null" ); + } + Map attrs = new HashMap<>( dom.getAttributes() ); + attrs.put( name, value ); + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ); + } + + // ---------------------------------------------------------------------- + // Child handling + // ---------------------------------------------------------------------- + + public Xpp3Dom getChild( int i ) + { + return new Xpp3Dom( dom.getChildren().get( i ) ); + } + + public Xpp3Dom getChild( String name ) + { + Dom child = dom.getChild( name ); + return child != null ? new Xpp3Dom( child ) : null; + } + + public void addChild( Xpp3Dom xpp3Dom ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.add( xpp3Dom.dom ); + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ); + } + + public Xpp3Dom[] getChildren() + { + return dom.getChildren().stream() + .map( Xpp3Dom::new ).toArray( Xpp3Dom[]::new ); + } + + public Xpp3Dom[] getChildren( String name ) + { + return dom.getChildren().stream() + .filter( c -> c.getName().equals( name ) ) + .map( Xpp3Dom::new ).toArray( Xpp3Dom[]::new ); + } + + public int getChildCount() + { + return dom.getChildren().size(); + } + + public void removeChild( int i ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.remove( i ); + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ); + } + + public void removeChild( Xpp3Dom child ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.remove( child.dom ); + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ); + } + + // ---------------------------------------------------------------------- + // Parent handling + // ---------------------------------------------------------------------- + + public Xpp3Dom getParent() + { + throw new UnsupportedOperationException(); + } + + public void setParent( Xpp3Dom parent ) + { + } + + // ---------------------------------------------------------------------- + // Input location handling + // ---------------------------------------------------------------------- + + /** + * @since 3.2.0 + * @return input location + */ + public Object getInputLocation() + { + return dom.getInputLocation(); + } + + /** + * @since 3.2.0 + * @param inputLocation input location to set + */ + public void setInputLocation( Object inputLocation ) + { + this.dom = new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), dom.getChildren(), inputLocation ); + } + + // ---------------------------------------------------------------------- + // Helpers + // ---------------------------------------------------------------------- + + public void writeToSerializer( String namespace, XmlSerializer serializer ) + throws IOException + { + // TODO: WARNING! Later versions of plexus-utils psit out an header due to thinking this is a new + // document - not the desired behaviour! + SerializerXMLWriter xmlWriter = new SerializerXMLWriter( namespace, serializer ); + Xpp3DomWriter.write( xmlWriter, this ); + if ( xmlWriter.getExceptions().size() > 0 ) + { + throw (IOException) xmlWriter.getExceptions().get( 0 ); + } + } + + /** + * Merges one DOM into another, given a specific algorithm and possible override points for that algorithm.

+ * The algorithm is as follows: + *

    + *
  1. if the recessive DOM is null, there is nothing to do... return.
  2. + *
  3. Determine whether the dominant node will suppress the recessive one (flag=mergeSelf). + *
      + *
    1. retrieve the 'combine.self' attribute on the dominant node, and try to match against 'override'... + * if it matches 'override', then set mergeSelf == false...the dominant node suppresses the recessive one + * completely.
    2. + *
    3. otherwise, use the default value for mergeSelf, which is true...this is the same as specifying + * 'combine.self' == 'merge' as an attribute of the dominant root node.
    4. + *
  4. + *
  5. If mergeSelf == true + *
      + *
    1. if the dominant root node's value is empty, set it to the recessive root node's value
    2. + *
    3. For each attribute in the recessive root node which is not set in the dominant root node, set it.
    4. + *
    5. Determine whether children from the recessive DOM will be merged or appended to the dominant DOM as + * siblings (flag=mergeChildren). + *
        + *
      1. if childMergeOverride is set (non-null), use that value (true/false)
      2. + *
      3. retrieve the 'combine.children' attribute on the dominant node, and try to match against + * 'append'...
      4. + *
      5. if it matches 'append', then set mergeChildren == false...the recessive children will be appended as + * siblings of the dominant children.
      6. + *
      7. otherwise, use the default value for mergeChildren, which is true...this is the same as specifying + * 'combine.children' == 'merge' as an attribute on the dominant root node.
      8. + *
    6. + *
    7. Iterate through the recessive children, and: + *
        + *
      1. if mergeChildren == true and there is a corresponding dominant child (matched by element name), + * merge the two.
      2. + *
      3. otherwise, add the recessive child as a new child on the dominant root node.
      4. + *
    8. + *
  6. + *
+ */ + private static void mergeIntoXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride ) + { + // TODO: share this as some sort of assembler, implement a walk interface? + if ( recessive == null ) + { + return; + } + dominant.dom = dominant.dom.merge( recessive.dom, childMergeOverride ); + } + + /** + * Merge two DOMs, with one having dominance in the case of collision. + * + * @see #CHILDREN_COMBINATION_MODE_ATTRIBUTE + * @see #SELF_COMBINATION_MODE_ATTRIBUTE + * @param dominant The dominant DOM into which the recessive value/attributes/children will be merged + * @param recessive The recessive DOM, which will be merged into the dominant DOM + * @param childMergeOverride Overrides attribute flags to force merging or appending of child elements into the + * dominant DOM + * @return merged DOM + */ + public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive, Boolean childMergeOverride ) + { + if ( dominant != null ) + { + mergeIntoXpp3Dom( dominant, recessive, childMergeOverride ); + return dominant; + } + return recessive; + } + + /** + * Merge two DOMs, with one having dominance in the case of collision. Merge mechanisms (vs. override for nodes, or + * vs. append for children) is determined by attributes of the dominant root node. + * + * @see #CHILDREN_COMBINATION_MODE_ATTRIBUTE + * @see #SELF_COMBINATION_MODE_ATTRIBUTE + * @param dominant The dominant DOM into which the recessive value/attributes/children will be merged + * @param recessive The recessive DOM, which will be merged into the dominant DOM + * @return merged DOM + */ + public static Xpp3Dom mergeXpp3Dom( Xpp3Dom dominant, Xpp3Dom recessive ) + { + if ( dominant != null ) + { + mergeIntoXpp3Dom( dominant, recessive, null ); + return dominant; + } + return recessive; + } + + // ---------------------------------------------------------------------- + // Standard object handling + // ---------------------------------------------------------------------- + + @Override + public boolean equals( Object obj ) + { + if ( obj == this ) + { + return true; + } + + if ( !( obj instanceof Xpp3Dom ) ) + { + return false; + } + + Xpp3Dom dom = (Xpp3Dom) obj; + return this.dom.equals( dom.dom ); + } + + @Override + public int hashCode() + { + return dom.hashCode(); + } + + @Override + public String toString() + { + return dom.toString(); + } + + public String toUnescapedString() + { + return ( ( Xpp3Dom ) dom ).toUnescapedString(); + } + + public static boolean isNotEmpty( String str ) + { + return ( ( str != null ) && ( str.length() > 0 ) ); + } + + public static boolean isEmpty( String str ) + { + return ( ( str == null ) || ( str.trim().length() == 0 ) ); + } + +} diff --git a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java new file mode 100644 index 000000000000..bdcfc4e454f5 --- /dev/null +++ b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3DomBuilder.java @@ -0,0 +1,110 @@ +package org.codehaus.plexus.util.xml; + +/* + * 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. + */ + +import java.io.IOException; +import java.io.InputStream; +import java.io.Reader; + +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; + +/** + * @version $Id$ + */ +public class Xpp3DomBuilder +{ + private static final boolean DEFAULT_TRIM = true; + + public static Xpp3Dom build( Reader reader ) + throws XmlPullParserException, IOException + { + return build( reader, null ); + } + + /** + * @since 3.2.0 + */ + public static Xpp3Dom build( Reader reader, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return build( reader, DEFAULT_TRIM, locationBuilder ); + } + + public static Xpp3Dom build( InputStream is, String encoding ) + throws XmlPullParserException, IOException + { + return build( is, encoding, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( InputStream is, String encoding, boolean trim ) + throws XmlPullParserException, IOException + { + return new Xpp3Dom( org.apache.maven.internal.xml.Xpp3DomBuilder.build( is, encoding, trim ) ); + } + + public static Xpp3Dom build( Reader reader, boolean trim ) + throws XmlPullParserException, IOException + { + return build( reader, trim, null ); + } + + /** + * @since 3.2.0 + */ + public static Xpp3Dom build( Reader reader, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return new Xpp3Dom( org.apache.maven.internal.xml.Xpp3DomBuilder.build( + reader, trim, locationBuilder != null ? locationBuilder::toInputLocation : null ) ); + } + + public static Xpp3Dom build( XmlPullParser parser ) + throws XmlPullParserException, IOException + { + return build( parser, DEFAULT_TRIM ); + } + + public static Xpp3Dom build( XmlPullParser parser, boolean trim ) + throws XmlPullParserException, IOException + { + return build( parser, trim, null ); + } + + /** + * @since 3.2.0 + */ + public static Xpp3Dom build( XmlPullParser parser, boolean trim, InputLocationBuilder locationBuilder ) + throws XmlPullParserException, IOException + { + return new Xpp3Dom( org.apache.maven.internal.xml.Xpp3DomBuilder.build( + parser, trim, locationBuilder != null ? locationBuilder::toInputLocation : null ) ); + } + + /** + * Input location builder interface, to be implemented to choose how to store data. + * + * @since 3.2.0 + */ + public interface InputLocationBuilder + { + Object toInputLocation( XmlPullParser parser ); + } +} From b1e95db3bc83c96b1b99bb270089598f2df08aea Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Apr 2022 09:18:07 +0200 Subject: [PATCH 08/98] Remove debug logging --- .../modello/plugin/velocity/ModelloVelocityMojo.java | 2 -- .../codehaus/modello/plugin/velocity/VelocityGenerator.java | 5 ----- 2 files changed, 7 deletions(-) diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java index 3b82a8f5ee8c..604d54f542e7 100644 --- a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/ModelloVelocityMojo.java @@ -64,8 +64,6 @@ protected void customizeParameters( Properties parameters ) Map params = this.params != null ? this.params.stream().collect( Collectors.toMap( s -> s.substring( 0, s.indexOf( '=' ) ), s -> s.substring( s.indexOf( '=' ) + 1 ) ) ) : Collections.emptyMap(); - getLog().warn( "templates: " + templates ); - getLog().warn( "params: " + params ); parameters.put( "basedir", Objects.requireNonNull( getBasedir(), "basedir is null" ) ); parameters.put( VelocityGenerator.VELOCITY_TEMPLATES, String.join( ",", templates ) ); parameters.put( VelocityGenerator.VELOCITY_PARAMETERS, params ); diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java index 2c0c999d787d..a5680d0c912b 100644 --- a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java @@ -76,11 +76,6 @@ public void generate( Model model, Properties parameters ) throws ModelloExcepti context.put( "model", model ); context.put( "Helper", new Helper( version ) ); - for ( String key : context.getKeys() ) - { - getLogger().warn( "context: " + key + " -> " + context.get( key ) ); - } - for ( String templatePath : templates.split( "," ) ) { Template template = velocity.getTemplate( templatePath ); From 8c3f314e49f3d88b3dbb16441146a12b7b0b2144 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Apr 2022 09:31:12 +0200 Subject: [PATCH 09/98] Fix velocity generator on windows --- .../codehaus/modello/plugin/velocity/VelocityGenerator.java | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java index a5680d0c912b..839471f5fdbd 100644 --- a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java @@ -109,8 +109,12 @@ public void write( char[] cbuf, int off, int len ) throws IOException { for ( int i = 0; i < len; i++ ) { - if ( cbuf[ off + i] == '\n' ) + if ( cbuf[ off + i ] == '\n' ) { + if ( sb.length() > 0 && sb.charAt( sb.length() - 1 ) == '\r' ) + { + sb.setLength( sb.length() - 1 ); + } writeLine( sb.toString() ); sb.setLength( 0 ); } From 60c698f485fefba8f4f46251cbbdc71a02cb11ef Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Apr 2022 14:18:54 +0200 Subject: [PATCH 10/98] Fix build consumer model merge --- .../model/building/FileToRawModelMerger.java | 21 ++++++++++++------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java index a46bd6bcc3e9..5918dbc415ed 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java @@ -21,6 +21,7 @@ import java.util.Iterator; import java.util.Map; +import java.util.stream.Collectors; import org.apache.maven.api.model.Build; import org.apache.maven.api.model.BuildBase; @@ -85,8 +86,9 @@ protected void mergeDependencyManagement_Dependencies( DependencyManagement.Buil boolean sourceDominant, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); - target.getDependencies().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.dependencies( target.getDependencies().stream() + .map( d -> mergeDependency( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override @@ -135,8 +137,9 @@ protected void mergeModel_Profiles( Model.Builder builder, Map context ) { Iterator sourceIterator = source.getProfiles().iterator(); - target.getProfiles().forEach( t -> mergeProfile( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.profiles( target.getProfiles().stream() + .map( d -> mergeProfile( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override @@ -145,8 +148,9 @@ protected void mergeModelBase_Dependencies( ModelBase.Builder builder, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); - target.getDependencies().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.dependencies( target.getDependencies().stream() + .map( d -> mergeDependency( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override @@ -171,8 +175,9 @@ protected void mergePlugin_Dependencies( Plugin.Builder builder, Map context ) { Iterator sourceIterator = source.getDependencies().iterator(); - target.getDependencies().forEach( t -> mergeDependency( t, sourceIterator.next(), sourceDominant, - context ) ); + builder.dependencies( target.getDependencies().stream() + .map( d -> mergeDependency( d, sourceIterator.next(), sourceDominant, context ) ) + .collect( Collectors.toList() ) ); } @Override From 7a5e38f92e02c20c9e9d1baaabb77ae2dc938a18 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Apr 2022 14:27:23 +0200 Subject: [PATCH 11/98] Extract enums in their own classes --- .../main/java/org/apache/maven/api/Event.java | 26 +- .../java/org/apache/maven/api/EventType.java | 48 +++ .../java/org/apache/maven/api/Metadata.java | 7 +- .../org/apache/maven/api/MetadataStorage.java | 28 ++ .../api/services/ProjectBuilderProblem.java | 14 +- .../ProjectBuilderProblemSeverity.java | 32 ++ .../maven/api/services/ProjectManager.java | 8 - .../maven/api/services/ResolutionScope.java | 33 ++ .../src/main/mdo/ImmutableCollections.java | 333 ++++++++++++++++++ .../internal/impl/DefaultProjectBuilder.java | 5 +- .../internal/impl/DefaultProjectManager.java | 1 + 11 files changed, 481 insertions(+), 54 deletions(-) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java create mode 100644 api/maven-api-model/src/main/mdo/ImmutableCollections.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java index 37da3d5765b8..088e8852a056 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java @@ -29,37 +29,13 @@ public interface Event { - /** - * The possible types of execution events. - */ - enum Type - { - ProjectDiscoveryStarted, - SessionStarted, - SessionEnded, - ProjectSkipped, - ProjectStarted, - ProjectSucceeded, - ProjectFailed, - MojoSkipped, - MojoStarted, - MojoSucceeded, - MojoFailed, - ForkStarted, - ForkSucceeded, - ForkFailed, - ForkedProjectStarted, - ForkedProjectSucceeded, - ForkedProjectFailed, - } - /** * Gets the type of the event. * * @return The type of the event, never {@code null}. */ @Nonnull - Type getType(); + EventType getType(); /** * Gets the session from which this event originates. diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java new file mode 100644 index 000000000000..e8a7fda538a9 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java @@ -0,0 +1,48 @@ +package org.apache.maven.api; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * The possible types of execution events. + * + * TODO: those values are lower cased, while other events are upper-case + * we need to align on one strategy + * see also {@link MetadataStorage} and {@link org.apache.maven.api.services.ResolutionScope} + */ +public enum EventType +{ + ProjectDiscoveryStarted, + SessionStarted, + SessionEnded, + ProjectSkipped, + ProjectStarted, + ProjectSucceeded, + ProjectFailed, + MojoSkipped, + MojoStarted, + MojoSucceeded, + MojoFailed, + ForkStarted, + ForkSucceeded, + ForkFailed, + ForkedProjectStarted, + ForkedProjectSucceeded, + ForkedProjectFailed, +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java index d0b83eff15a8..ec4a9b15dca2 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java @@ -31,11 +31,6 @@ public interface Metadata String getVersion(); - enum Storage - { - Group, Artifact, Version - } - - Storage getStorage(); + MetadataStorage getStorage(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java new file mode 100644 index 000000000000..40e6d509786e --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java @@ -0,0 +1,28 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +/** + * Storage location for metadata + */ +public enum MetadataStorage +{ + Group, Artifact, Version +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java index af9dc4763590..4b32d5738504 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java @@ -30,18 +30,6 @@ public interface ProjectBuilderProblem { - /** - * The different severity levels for a problem, in decreasing order. - */ - enum Severity - { - - FATAL, // - ERROR, // - WARNING // - - } - /** * Gets the hint about the source of the problem. While the syntax of this hint is unspecified and depends on the * creator of the problem, the general expectation is that the hint provides sufficient information to the user to @@ -96,6 +84,6 @@ enum Severity * * @return The severity level of this problem, never {@code null}. */ - Severity getSeverity(); + ProjectBuilderProblemSeverity getSeverity(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java new file mode 100644 index 000000000000..4b40a51a1d53 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java @@ -0,0 +1,32 @@ +package org.apache.maven.api.services; + +/* + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + */ + +/** + * The different severity levels for a problem, in decreasing order. + */ +public enum ProjectBuilderProblemSeverity +{ + + FATAL, // + ERROR, // + WARNING // + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java index f66732265a7b..cee11892a720 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -82,12 +82,4 @@ default void attachArtifact( Session session, Project project, String type, Path Node getCollectedDependencies( Project project, ResolutionScope scope ); - enum ResolutionScope - { - Compile, - CompileRuntime, - Runtime, - RuntimeSystem, - Test - } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java new file mode 100644 index 000000000000..e953f1db60fd --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java @@ -0,0 +1,33 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +/** + * Resolution scope + * TODO: merge this with {@link org.apache.maven.api.plugin.annotations.ResolutionScope} + */ +public enum ResolutionScope +{ + Compile, + CompileRuntime, + Runtime, + RuntimeSystem, + Test +} diff --git a/api/maven-api-model/src/main/mdo/ImmutableCollections.java b/api/maven-api-model/src/main/mdo/ImmutableCollections.java new file mode 100644 index 000000000000..d6fba9aab96b --- /dev/null +++ b/api/maven-api-model/src/main/mdo/ImmutableCollections.java @@ -0,0 +1,333 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.lang.reflect.Array; +import java.util.AbstractList; +import java.util.Arrays; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.RandomAccess; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +public class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + default: + return (List) new ListN<>( collection ); + } + } + } + + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + public List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class ListN extends AbstractImmutableList + { + private final E[] elements; + + private ListN( Collection elements ) + { + E[] tmp = (E[]) Array.newInstance( elements.getClass().getComponentType(), elements.size() ); + this.elements = elements.toArray( tmp ); + } + + @Override + public E get( int index ) + { + return elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private static abstract class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr(); + } + + @Override + public ListIterator listIterator() + { + return new Itr(); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0) + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + if ( toIndex > size() ) + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + if ( fromIndex > toIndex ) + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + public SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + class Itr implements ListIterator + { + int index; + + public Itr() + { + this.index = 0; + } + + public Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java index 98841c8340b7..25e39ef40f2c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java @@ -35,6 +35,7 @@ import org.apache.maven.api.Artifact; import org.apache.maven.api.Node; import org.apache.maven.api.Project; +import org.apache.maven.api.services.ProjectBuilderProblemSeverity; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.building.ModelProblem; import org.apache.maven.model.building.ModelSource; @@ -215,9 +216,9 @@ public String getMessage() } @Override - public Severity getSeverity() + public ProjectBuilderProblemSeverity getSeverity() { - return Severity.valueOf( problem.getSeverity().name() ); + return ProjectBuilderProblemSeverity.valueOf( problem.getSeverity().name() ); } }; } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java index 78ddff441eba..7af8591ffd18 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java @@ -35,6 +35,7 @@ import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ProjectManager; +import org.apache.maven.api.services.ResolutionScope; public class DefaultProjectManager implements ProjectManager { From 7a357e93a544e02bfe0c20b27128b18520997e10 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Apr 2022 16:10:13 +0200 Subject: [PATCH 12/98] Fix ITs --- .../xml/internal/PlexusXmlBeanConverter.java | 488 ++++++++++++++++++ .../sisu/plexus/PlexusXmlBeanConverter.java | 486 +++++++++++++++++ maven-model/src/main/mdo/model-v3.vm | 10 +- .../settings/merge/MavenSettingsMerger.java | 36 +- 4 files changed, 991 insertions(+), 29 deletions(-) create mode 100644 maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java create mode 100644 maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java diff --git a/maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java b/maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java new file mode 100644 index 000000000000..96bfb35d37c7 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java @@ -0,0 +1,488 @@ +package org.apache.maven.xml.internal; + +/* + * 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. + */ + +import javax.annotation.Priority; +import javax.inject.Inject; + +import java.io.StringReader; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.Singleton; +import com.google.inject.TypeLiteral; +import com.google.inject.spi.TypeConverter; +import com.google.inject.spi.TypeConverterBinding; +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.eclipse.sisu.bean.BeanProperties; +import org.eclipse.sisu.bean.BeanProperty; +import org.eclipse.sisu.inject.Logs; +import org.eclipse.sisu.inject.TypeArguments; +import org.eclipse.sisu.plexus.PlexusBeanConverter; +import org.eclipse.sisu.plexus.Roles; + +/** + * {@link PlexusBeanConverter} {@link Module} that converts Plexus XML configuration into beans. + */ +@Singleton +@Priority( 10 ) +public final class PlexusXmlBeanConverter + implements PlexusBeanConverter +{ + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + private static final String CONVERSION_ERROR = "Cannot convert: \"%s\" to: %s"; + + // ---------------------------------------------------------------------- + // Implementation fields + // ---------------------------------------------------------------------- + + private final Collection typeConverterBindings; + + // ---------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------- + + @Inject + PlexusXmlBeanConverter( final Injector injector ) + { + typeConverterBindings = injector.getTypeConverterBindings(); + } + + // ---------------------------------------------------------------------- + // Public methods + // ---------------------------------------------------------------------- + + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public Object convert( final TypeLiteral role, final String value ) + { + if ( value.trim().startsWith( "<" ) ) + { + try + { + final MXParser parser = new MXParser(); + parser.setInput( new StringReader( value ) ); + parser.nextTag(); + + return parse( parser, role ); + } + catch ( final Exception e ) + { + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, role ), e ); + } + } + + return convertText( value, role ); + } + + // ---------------------------------------------------------------------- + // Implementation methods + // ---------------------------------------------------------------------- + + /** + * Parses a sequence of XML elements and converts them to the given target type. + * + * @param parser The XML parser + * @param toType The target type + * @return Converted instance of the target type + */ + private Object parse( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + parser.require( XmlPullParser.START_TAG, null, null ); + + final Class rawType = toType.getRawType(); + if ( Dom.class.isAssignableFrom( rawType ) ) + { + return org.apache.maven.internal.xml.Xpp3DomBuilder.build( parser ); + } + if ( Xpp3Dom.class.isAssignableFrom( rawType ) ) + { + return parseXpp3Dom( parser ); + } + if ( Properties.class.isAssignableFrom( rawType ) ) + { + return parseProperties( parser ); + } + if ( Map.class.isAssignableFrom( rawType ) ) + { + return parseMap( parser, TypeArguments.get( toType.getSupertype( Map.class ), 1 ) ); + } + if ( Collection.class.isAssignableFrom( rawType ) ) + { + return parseCollection( parser, TypeArguments.get( toType.getSupertype( Collection.class ), 0 ) ); + } + if ( rawType.isArray() ) + { + return parseArray( parser, TypeArguments.get( toType, 0 ) ); + } + return parseBean( parser, toType, rawType ); + } + + /** + * Parses an XML subtree and converts it to the {@link Xpp3Dom} type. + * + * @param parser The XML parser + * @return Converted Xpp3Dom instance + */ + private static Xpp3Dom parseXpp3Dom( final XmlPullParser parser ) + throws Exception + { + return Xpp3DomBuilder.build( parser ); + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Properties} type. + * + * @param parser The XML parser + * @return Converted Properties instance + */ + private static Properties parseProperties( final XmlPullParser parser ) + throws Exception + { + final Properties properties = newImplementation( parser, Properties.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + parser.nextTag(); + // 'name-then-value' or 'value-then-name' + if ( "name".equals( parser.getName() ) ) + { + final String name = parser.nextText(); + parser.nextTag(); + properties.put( name, parser.nextText() ); + } + else + { + final String value = parser.nextText(); + parser.nextTag(); + properties.put( parser.nextText(), value ); + } + parser.nextTag(); + } + return properties; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Map} type. + * + * @param parser The XML parser + * @return Converted Map instance + */ + private Map parseMap( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + @SuppressWarnings( "unchecked" ) + final Map map = newImplementation( parser, HashMap.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + map.put( parser.getName(), parse( parser, toType ) ); + } + return map; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Collection} type. + * + * @param parser The XML parser + * @return Converted Collection instance + */ + private Collection parseCollection( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + @SuppressWarnings( "unchecked" ) + final Collection collection = newImplementation( parser, ArrayList.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + collection.add( parse( parser, toType ) ); + } + return collection; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate array type. + * + * @param parser The XML parser + * @return Converted array instance + */ + private Object parseArray( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + // convert to a collection first then convert that into an array + final Collection collection = parseCollection( parser, toType ); + final Object array = Array.newInstance( toType.getRawType(), collection.size() ); + + int i = 0; + for ( final Object element : collection ) + { + Array.set( array, i++, element ); + } + + return array; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate bean type. + * + * @param parser The XML parser + * @return Converted bean instance + */ + private Object parseBean( final MXParser parser, final TypeLiteral toType, final Class rawType ) + throws Exception + { + final Class clazz = loadImplementation( parseImplementation( parser ), rawType ); + + // simple bean? assumes string constructor + if ( parser.next() == XmlPullParser.TEXT ) + { + final String text = parser.getText(); + + // confirm element doesn't contain nested XML + if ( parser.next() != XmlPullParser.START_TAG ) + { + return convertText( text, clazz == rawType ? toType : TypeLiteral.get( clazz ) ); + } + } + + if ( String.class == clazz ) + { + // mimic plexus: discard any strings containing nested XML + while ( parser.getEventType() == XmlPullParser.START_TAG ) + { + final String pos = parser.getPositionDescription(); + Logs.warn( "Expected TEXT, not XML: {}", pos, new Throwable() ); + parser.skipSubTree(); + parser.nextTag(); + } + return ""; + } + + final Object bean = newImplementation( clazz ); + + // build map of all known bean properties belonging to the chosen implementation + final Map> propertyMap = new HashMap>(); + for ( final BeanProperty property : new BeanProperties( clazz ) ) + { + final String name = property.getName(); + if ( !propertyMap.containsKey( name ) ) + { + propertyMap.put( name, property ); + } + } + + while ( parser.getEventType() == XmlPullParser.START_TAG ) + { + // update properties inside the bean, guided by the cached property map + final BeanProperty property = propertyMap.get( Roles.camelizeName( parser.getName() ) ); + if ( property != null ) + { + property.set( bean, parse( parser, property.getType() ) ); + parser.nextTag(); + } + else + { + throw new XmlPullParserException( "Unknown bean property: " + parser.getName(), parser, null ); + } + } + + return bean; + } + + /** + * Parses an XML element looking for the name of a custom implementation. + * + * @param parser The XML parser + * @return Name of the custom implementation; otherwise {@code null} + */ + private static String parseImplementation( final XmlPullParser parser ) + { + return parser.getAttributeValue( null, "implementation" ); + } + + /** + * Attempts to load the named implementation, uses default implementation if no name is given. + * + * @param name The optional implementation name + * @param defaultClazz The default implementation type + * @return Custom implementation type if one was given; otherwise default implementation type + */ + private static Class loadImplementation( final String name, final Class defaultClazz ) + { + if ( null == name ) + { + return defaultClazz; // just use the default type + } + + // TCCL allows surrounding container to influence class loading policy + final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + if ( tccl != null ) + { + try + { + return tccl.loadClass( name ); + } + catch ( final Exception e ) + { + // drop through... + } + catch ( final LinkageError e ) + { + // drop through... + } + } + + // assume custom type is in same class space as default + final ClassLoader peer = defaultClazz.getClassLoader(); + if ( peer != null ) + { + try + { + return peer.loadClass( name ); + } + catch ( final Exception e ) + { + // drop through... + } + catch ( final LinkageError e ) + { + // drop through... + } + } + + try + { + // last chance - classic model + return Class.forName( name ); + } + catch ( final Exception e ) + { + throw new TypeNotPresentException( name, e ); + } + catch ( final LinkageError e ) + { + throw new TypeNotPresentException( name, e ); + } + } + + /** + * Creates an instance of the given implementation using the default constructor. + * + * @param clazz The implementation type + * @return Instance of given implementation + */ + private static T newImplementation( final Class clazz ) + { + try + { + return clazz.newInstance(); + } + catch ( final Exception e ) + { + throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); + } + catch ( final LinkageError e ) + { + throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); + } + } + + /** + * Creates an instance of the given implementation using the given string, assumes a public string constructor. + * + * @param clazz The implementation type + * @param value The string argument + * @return Instance of given implementation, constructed using the the given string + */ + private static T newImplementation( final Class clazz, final String value ) + { + try + { + return clazz.getConstructor( String.class ).newInstance( value ); + } + catch ( final Exception e ) + { + final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), cause ); + } + catch ( final LinkageError e ) + { + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), e ); + } + } + + /** + * Creates an instance of the implementation named in the current XML element, or the default if no name is given. + * + * @param parser The XML parser + * @param defaultClazz The default implementation type + * @return Instance of custom implementation if one was given; otherwise instance of default type + */ + @SuppressWarnings( "unchecked" ) + private static T newImplementation( final XmlPullParser parser, final Class defaultClazz ) + { + return (T) newImplementation( loadImplementation( parseImplementation( parser ), defaultClazz ) ); + } + + /** + * Converts the given string to the target type, using {@link TypeConverter}s registered with the {@link Injector}. + * + * @param value The string value + * @param toType The target type + * @return Converted instance of the target type + */ + private Object convertText( final String value, final TypeLiteral toType ) + { + final String text = value.trim(); + + final Class rawType = toType.getRawType(); + if ( rawType.isAssignableFrom( String.class ) ) + { + return text; // compatible type => no conversion needed + } + + // use temporary Key as quick way to auto-box primitive types into their equivalent object types + final TypeLiteral boxedType = rawType.isPrimitive() ? Key.get( rawType ).getTypeLiteral() : toType; + + for ( final TypeConverterBinding b : typeConverterBindings ) + { + if ( b.getTypeMatcher().matches( boxedType ) ) + { + return b.getTypeConverter().convert( text, toType ); + } + } + + // last chance => attempt to create an instance of the expected type: use the string if non-empty + return text.length() == 0 ? newImplementation( rawType ) : newImplementation( rawType, text ); + } +} diff --git a/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java b/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java new file mode 100644 index 000000000000..e10551ae93bc --- /dev/null +++ b/maven-embedder/src/main/java/org/eclipse/sisu/plexus/PlexusXmlBeanConverter.java @@ -0,0 +1,486 @@ +package org.eclipse.sisu.plexus; + +/* + * 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. + */ + +import javax.annotation.Priority; +import javax.inject.Inject; +import javax.inject.Singleton; + +import java.io.StringReader; +import java.lang.reflect.Array; +import java.lang.reflect.InvocationTargetException; +import java.util.ArrayList; +import java.util.Collection; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; + +import com.google.inject.Injector; +import com.google.inject.Key; +import com.google.inject.Module; +import com.google.inject.TypeLiteral; +import com.google.inject.spi.TypeConverter; +import com.google.inject.spi.TypeConverterBinding; +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.eclipse.sisu.bean.BeanProperties; +import org.eclipse.sisu.bean.BeanProperty; +import org.eclipse.sisu.inject.Logs; +import org.eclipse.sisu.inject.TypeArguments; + +/** + * {@link PlexusBeanConverter} {@link Module} that converts Plexus XML configuration into beans. + */ +@Singleton +@Priority( 10 ) +public final class PlexusXmlBeanConverter + implements PlexusBeanConverter +{ + // ---------------------------------------------------------------------- + // Constants + // ---------------------------------------------------------------------- + + private static final String CONVERSION_ERROR = "Cannot convert: \"%s\" to: %s"; + + // ---------------------------------------------------------------------- + // Implementation fields + // ---------------------------------------------------------------------- + + private final Collection typeConverterBindings; + + // ---------------------------------------------------------------------- + // Constructors + // ---------------------------------------------------------------------- + + @Inject + PlexusXmlBeanConverter( final Injector injector ) + { + typeConverterBindings = injector.getTypeConverterBindings(); + } + + // ---------------------------------------------------------------------- + // Public methods + // ---------------------------------------------------------------------- + + @SuppressWarnings( { "unchecked", "rawtypes" } ) + public Object convert( final TypeLiteral role, final String value ) + { + if ( value.trim().startsWith( "<" ) ) + { + try + { + final MXParser parser = new MXParser(); + parser.setInput( new StringReader( value ) ); + parser.nextTag(); + + return parse( parser, role ); + } + catch ( final Exception e ) + { + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, role ), e ); + } + } + + return convertText( value, role ); + } + + // ---------------------------------------------------------------------- + // Implementation methods + // ---------------------------------------------------------------------- + + /** + * Parses a sequence of XML elements and converts them to the given target type. + * + * @param parser The XML parser + * @param toType The target type + * @return Converted instance of the target type + */ + private Object parse( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + parser.require( XmlPullParser.START_TAG, null, null ); + + final Class rawType = toType.getRawType(); + if ( Dom.class.isAssignableFrom( rawType ) ) + { + return org.apache.maven.internal.xml.Xpp3DomBuilder.build( parser ); + } + if ( Xpp3Dom.class.isAssignableFrom( rawType ) ) + { + return parseXpp3Dom( parser ); + } + if ( Properties.class.isAssignableFrom( rawType ) ) + { + return parseProperties( parser ); + } + if ( Map.class.isAssignableFrom( rawType ) ) + { + return parseMap( parser, TypeArguments.get( toType.getSupertype( Map.class ), 1 ) ); + } + if ( Collection.class.isAssignableFrom( rawType ) ) + { + return parseCollection( parser, TypeArguments.get( toType.getSupertype( Collection.class ), 0 ) ); + } + if ( rawType.isArray() ) + { + return parseArray( parser, TypeArguments.get( toType, 0 ) ); + } + return parseBean( parser, toType, rawType ); + } + + /** + * Parses an XML subtree and converts it to the {@link Xpp3Dom} type. + * + * @param parser The XML parser + * @return Converted Xpp3Dom instance + */ + private static Xpp3Dom parseXpp3Dom( final XmlPullParser parser ) + throws Exception + { + return Xpp3DomBuilder.build( parser ); + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Properties} type. + * + * @param parser The XML parser + * @return Converted Properties instance + */ + private static Properties parseProperties( final XmlPullParser parser ) + throws Exception + { + final Properties properties = newImplementation( parser, Properties.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + parser.nextTag(); + // 'name-then-value' or 'value-then-name' + if ( "name".equals( parser.getName() ) ) + { + final String name = parser.nextText(); + parser.nextTag(); + properties.put( name, parser.nextText() ); + } + else + { + final String value = parser.nextText(); + parser.nextTag(); + properties.put( parser.nextText(), value ); + } + parser.nextTag(); + } + return properties; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Map} type. + * + * @param parser The XML parser + * @return Converted Map instance + */ + private Map parseMap( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + @SuppressWarnings( "unchecked" ) + final Map map = newImplementation( parser, HashMap.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + map.put( parser.getName(), parse( parser, toType ) ); + } + return map; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate {@link Collection} type. + * + * @param parser The XML parser + * @return Converted Collection instance + */ + private Collection parseCollection( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + @SuppressWarnings( "unchecked" ) + final Collection collection = newImplementation( parser, ArrayList.class ); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + collection.add( parse( parser, toType ) ); + } + return collection; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate array type. + * + * @param parser The XML parser + * @return Converted array instance + */ + private Object parseArray( final MXParser parser, final TypeLiteral toType ) + throws Exception + { + // convert to a collection first then convert that into an array + final Collection collection = parseCollection( parser, toType ); + final Object array = Array.newInstance( toType.getRawType(), collection.size() ); + + int i = 0; + for ( final Object element : collection ) + { + Array.set( array, i++, element ); + } + + return array; + } + + /** + * Parses a sequence of XML elements and converts them to the appropriate bean type. + * + * @param parser The XML parser + * @return Converted bean instance + */ + private Object parseBean( final MXParser parser, final TypeLiteral toType, final Class rawType ) + throws Exception + { + final Class clazz = loadImplementation( parseImplementation( parser ), rawType ); + + // simple bean? assumes string constructor + if ( parser.next() == XmlPullParser.TEXT ) + { + final String text = parser.getText(); + + // confirm element doesn't contain nested XML + if ( parser.next() != XmlPullParser.START_TAG ) + { + return convertText( text, clazz == rawType ? toType : TypeLiteral.get( clazz ) ); + } + } + + if ( String.class == clazz ) + { + // mimic plexus: discard any strings containing nested XML + while ( parser.getEventType() == XmlPullParser.START_TAG ) + { + final String pos = parser.getPositionDescription(); + Logs.warn( "Expected TEXT, not XML: {}", pos, new Throwable() ); + parser.skipSubTree(); + parser.nextTag(); + } + return ""; + } + + final Object bean = newImplementation( clazz ); + + // build map of all known bean properties belonging to the chosen implementation + final Map> propertyMap = new HashMap>(); + for ( final BeanProperty property : new BeanProperties( clazz ) ) + { + final String name = property.getName(); + if ( !propertyMap.containsKey( name ) ) + { + propertyMap.put( name, property ); + } + } + + while ( parser.getEventType() == XmlPullParser.START_TAG ) + { + // update properties inside the bean, guided by the cached property map + final BeanProperty property = propertyMap.get( Roles.camelizeName( parser.getName() ) ); + if ( property != null ) + { + property.set( bean, parse( parser, property.getType() ) ); + parser.nextTag(); + } + else + { + throw new XmlPullParserException( "Unknown bean property: " + parser.getName(), parser, null ); + } + } + + return bean; + } + + /** + * Parses an XML element looking for the name of a custom implementation. + * + * @param parser The XML parser + * @return Name of the custom implementation; otherwise {@code null} + */ + private static String parseImplementation( final XmlPullParser parser ) + { + return parser.getAttributeValue( null, "implementation" ); + } + + /** + * Attempts to load the named implementation, uses default implementation if no name is given. + * + * @param name The optional implementation name + * @param defaultClazz The default implementation type + * @return Custom implementation type if one was given; otherwise default implementation type + */ + private static Class loadImplementation( final String name, final Class defaultClazz ) + { + if ( null == name ) + { + return defaultClazz; // just use the default type + } + + // TCCL allows surrounding container to influence class loading policy + final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); + if ( tccl != null ) + { + try + { + return tccl.loadClass( name ); + } + catch ( final Exception e ) + { + // drop through... + } + catch ( final LinkageError e ) + { + // drop through... + } + } + + // assume custom type is in same class space as default + final ClassLoader peer = defaultClazz.getClassLoader(); + if ( peer != null ) + { + try + { + return peer.loadClass( name ); + } + catch ( final Exception e ) + { + // drop through... + } + catch ( final LinkageError e ) + { + // drop through... + } + } + + try + { + // last chance - classic model + return Class.forName( name ); + } + catch ( final Exception e ) + { + throw new TypeNotPresentException( name, e ); + } + catch ( final LinkageError e ) + { + throw new TypeNotPresentException( name, e ); + } + } + + /** + * Creates an instance of the given implementation using the default constructor. + * + * @param clazz The implementation type + * @return Instance of given implementation + */ + private static T newImplementation( final Class clazz ) + { + try + { + return clazz.newInstance(); + } + catch ( final Exception e ) + { + throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); + } + catch ( final LinkageError e ) + { + throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); + } + } + + /** + * Creates an instance of the given implementation using the given string, assumes a public string constructor. + * + * @param clazz The implementation type + * @param value The string argument + * @return Instance of given implementation, constructed using the the given string + */ + private static T newImplementation( final Class clazz, final String value ) + { + try + { + return clazz.getConstructor( String.class ).newInstance( value ); + } + catch ( final Exception e ) + { + final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), cause ); + } + catch ( final LinkageError e ) + { + throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), e ); + } + } + + /** + * Creates an instance of the implementation named in the current XML element, or the default if no name is given. + * + * @param parser The XML parser + * @param defaultClazz The default implementation type + * @return Instance of custom implementation if one was given; otherwise instance of default type + */ + @SuppressWarnings( "unchecked" ) + private static T newImplementation( final XmlPullParser parser, final Class defaultClazz ) + { + return (T) newImplementation( loadImplementation( parseImplementation( parser ), defaultClazz ) ); + } + + /** + * Converts the given string to the target type, using {@link TypeConverter}s registered with the {@link Injector}. + * + * @param value The string value + * @param toType The target type + * @return Converted instance of the target type + */ + private Object convertText( final String value, final TypeLiteral toType ) + { + final String text = value.trim(); + + final Class rawType = toType.getRawType(); + if ( rawType.isAssignableFrom( String.class ) ) + { + return text; // compatible type => no conversion needed + } + + // use temporary Key as quick way to auto-box primitive types into their equivalent object types + final TypeLiteral boxedType = rawType.isPrimitive() ? Key.get( rawType ).getTypeLiteral() : toType; + + for ( final TypeConverterBinding b : typeConverterBindings ) + { + if ( b.getTypeMatcher().matches( boxedType ) ) + { + return b.getTypeConverter().convert( text, toType ); + } + } + + // last chance => attempt to create an instance of the expected type: use the string if non-empty + return text.length() == 0 ? newImplementation( rawType ) : newImplementation( rawType, text ); + } +} diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 9b972015aead..488ebd807614 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -193,10 +193,14 @@ public class ${class.name} public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) { #if ( $field.type == "DOM" ) - org.codehaus.plexus.util.xml.Xpp3Dom dom = ( org.codehaus.plexus.util.xml.Xpp3Dom ) ${field.name}; - if ( ! Objects.equals( dom != null ? dom.getDom() : null, getDelegate().${pfx}${cap}() ) ) + if ( ${field.name} instanceof org.codehaus.plexus.util.xml.Xpp3Dom ) { - delegate = getDelegate().with${cap}( dom.getDom() ); + ${field.name} = ( ( org.codehaus.plexus.util.xml.Xpp3Dom ) ${field.name} ).getDom(); + } + org.apache.maven.api.xml.Dom dom = ( org.apache.maven.api.xml.Dom ) ${field.name}; + if ( ! Objects.equals( dom, getDelegate().${pfx}${cap}() ) ) + { + delegate = getDelegate().with${cap}( dom ); } #else if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) 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 0eec227744e0..c6d3b1827928 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 @@ -20,11 +20,13 @@ */ 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; @@ -59,36 +61,18 @@ else if ( recessive == null ) List dominantActiveProfiles = dominant.getActiveProfiles(); List recessiveActiveProfiles = recessive.getActiveProfiles(); - List mergedActiveProfiles = new ArrayList<>(); - if ( recessiveActiveProfiles != null ) - { - for ( String profileId : recessiveActiveProfiles ) - { - if ( dominantActiveProfiles == null || !dominantActiveProfiles.contains( profileId ) ) - { - mergedActiveProfiles.add( profileId ); - } - } - } + List mergedActiveProfiles = Stream.of( dominantActiveProfiles, recessiveActiveProfiles ) + .flatMap( Collection::stream ) + .distinct() + .collect( Collectors.toList() ); merged.activeProfiles( mergedActiveProfiles ); List dominantPluginGroupIds = dominant.getPluginGroups(); List recessivePluginGroupIds = recessive.getPluginGroups(); - List mergedPluginGroupIds = new ArrayList<>(); - if ( recessivePluginGroupIds != null ) - { - if ( dominantPluginGroupIds != null ) - { - mergedPluginGroupIds.addAll( dominantPluginGroupIds ); - } - for ( String pluginGroupId : recessivePluginGroupIds ) - { - if ( dominantPluginGroupIds == null || !dominantPluginGroupIds.contains( pluginGroupId ) ) - { - mergedPluginGroupIds.add( pluginGroupId ); - } - } - } + List mergedPluginGroupIds = Stream.of( dominantPluginGroupIds, recessivePluginGroupIds ) + .flatMap( Collection::stream ) + .distinct() + .collect( Collectors.toList() ); merged.pluginGroups( mergedPluginGroupIds ); String localRepository = StringUtils.isEmpty( dominant.getLocalRepository() ) From a9d678c0314e288153a193b1fe5b2e9a2c85d732 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Apr 2022 17:29:19 +0200 Subject: [PATCH 13/98] More fixes --- apache-maven/src/assembly/maven/bin/m2.conf | 1 + ...DefaultRepositorySystemSessionFactory.java | 25 +- ...faultLifecycleExecutionPlanCalculator.java | 5 +- .../DefaultMojoExecutionConfigurator.java | 7 +- .../apache/maven/plugin/MojoExecution.java | 20 +- .../internal/DefaultMavenPluginManager.java | 2 +- .../maven/project/ProjectModelResolver.java | 37 ++ .../xml/internal/PlexusXmlBeanConverter.java | 488 ------------------ .../maven/model/resolution/ModelResolver.java | 19 +- .../building/DefaultModelBuilderTest.java | 26 + .../internal/DefaultModelResolver.java | 37 ++ 11 files changed, 153 insertions(+), 514 deletions(-) delete mode 100644 maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java diff --git a/apache-maven/src/assembly/maven/bin/m2.conf b/apache-maven/src/assembly/maven/bin/m2.conf index 2235f820f5f0..1370a4c361ee 100644 --- a/apache-maven/src/assembly/maven/bin/m2.conf +++ b/apache-maven/src/assembly/maven/bin/m2.conf @@ -5,4 +5,5 @@ set maven.conf default ${maven.home}/conf [plexus.core] load ${maven.conf}/logging optionally ${maven.home}/lib/ext/*.jar +load ${maven.home}/lib/maven-*.jar load ${maven.home}/lib/*.jar diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index aa6781f309a5..492c09b3f82c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -26,17 +26,22 @@ import java.util.Collection; import java.util.Collections; import java.util.LinkedHashMap; +import java.util.List; import java.util.Map; +import java.util.stream.Collectors; import javax.inject.Inject; import javax.inject.Named; import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.xml.Dom; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.eventspy.internal.EventSpyDispatcher; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.feature.Features; +import org.apache.maven.internal.xml.XmlPlexusConfiguration; +import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.model.building.TransformerContext; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.apache.maven.rtinfo.RuntimeInformation; @@ -47,8 +52,7 @@ import org.apache.maven.settings.crypto.DefaultSettingsDecryptionRequest; import org.apache.maven.settings.crypto.SettingsDecrypter; import org.apache.maven.settings.crypto.SettingsDecryptionResult; -import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; -import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; import org.eclipse.aether.ConfigurationProperties; import org.eclipse.aether.DefaultRepositorySystemSession; @@ -227,17 +231,12 @@ else if ( request.isUpdateSnapshots() ) if ( server.getConfiguration() != null ) { - Xpp3Dom dom = (Xpp3Dom) server.getConfiguration(); - for ( int i = dom.getChildCount() - 1; i >= 0; i-- ) - { - Xpp3Dom child = dom.getChild( i ); - if ( "wagonProvider".equals( child.getName() ) ) - { - dom.removeChild( i ); - } - } - - XmlPlexusConfiguration config = new XmlPlexusConfiguration( dom ); + Dom dom = server.getConfiguration(); + List children = dom.getChildren().stream() + .filter( c -> !"wagonProvider".equals( c.getName() ) ) + .collect( Collectors.toList() ); + dom = new Xpp3Dom( dom.getName(), null, null, children, null ); + PlexusConfiguration config = XmlPlexusConfiguration.toPlexusConfiguration( dom ); configProps.put( "aether.connector.wagon.config." + server.getId(), config ); } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java index a9875b100e70..c352a079470e 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java @@ -316,7 +316,8 @@ private void finalizeMojoConfiguration( MojoExecution mojoExecution ) { MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); - Dom executionConfiguration = mojoExecution.getConfiguration(); + org.codehaus.plexus.util.xml.Xpp3Dom config = mojoExecution.getConfiguration(); + Dom executionConfiguration = config != null ? config.getDom() : null; if ( executionConfiguration == null ) { executionConfiguration = new Xpp3Dom( "configuration" ); @@ -561,7 +562,7 @@ private void injectLifecycleOverlay( Map> lifecycleM { for ( MojoExecution forkedExecution : forkedExecutions ) { - Dom forkedConfiguration = forkedExecution.getConfiguration(); + Dom forkedConfiguration = forkedExecution.getConfiguration().getDom(); forkedConfiguration = phaseConfiguration.merge( forkedConfiguration ); diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java index 3ac861311d70..75a1c7ba6f56 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultMojoExecutionConfigurator.java @@ -72,9 +72,12 @@ else if ( allowPluginLevelConfig ) pomConfiguration = plugin.getDelegate().getConfiguration(); } - Dom mojoConfiguration = Xpp3Dom.merge( mojoExecution.getConfiguration(), pomConfiguration ); + Dom mojoConfiguration = mojoExecution.getConfiguration() != null + ? mojoExecution.getConfiguration().getDom() : null; - mojoExecution.setConfiguration( mojoConfiguration ); + Dom mergedConfiguration = Xpp3Dom.merge( mojoConfiguration, pomConfiguration ); + + mojoExecution.setConfiguration( mergedConfiguration ); } } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java b/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java index c37c6cbfa3ca..5f6f0fd0dca8 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java @@ -41,7 +41,7 @@ public class MojoExecution private MojoDescriptor mojoDescriptor; - private Dom configuration; + private org.codehaus.plexus.util.xml.Xpp3Dom configuration; /** * Describes the source of an execution. @@ -103,13 +103,20 @@ public MojoExecution( MojoDescriptor mojoDescriptor, String executionId ) this.configuration = null; } - public MojoExecution( MojoDescriptor mojoDescriptor, Dom configuration ) + public MojoExecution( MojoDescriptor mojoDescriptor, org.codehaus.plexus.util.xml.Xpp3Dom configuration ) { this.mojoDescriptor = mojoDescriptor; this.configuration = configuration; this.executionId = null; } + public MojoExecution( MojoDescriptor mojoDescriptor, Dom configuration ) + { + this.mojoDescriptor = mojoDescriptor; + this.configuration = new org.codehaus.plexus.util.xml.Xpp3Dom( configuration ); + this.executionId = null; + } + /** * Gets the source of this execution. * @@ -140,16 +147,21 @@ public MojoDescriptor getMojoDescriptor() return mojoDescriptor; } - public Dom getConfiguration() + public org.codehaus.plexus.util.xml.Xpp3Dom getConfiguration() { return configuration; } - public void setConfiguration( Dom configuration ) + public void setConfiguration( org.codehaus.plexus.util.xml.Xpp3Dom configuration ) { this.configuration = configuration; } + public void setConfiguration( Dom configuration ) + { + this.configuration = new org.codehaus.plexus.util.xml.Xpp3Dom( configuration ); + } + public String identify() { StringBuilder sb = new StringBuilder( 256 ); diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 9da97072712b..707c6d8ce2d5 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -590,7 +590,7 @@ else if ( cause instanceof LinkageError ) ( (Mojo) mojo ).setLog( new MojoLogWrapper( mojoLogger ) ); } - Dom dom = mojoExecution.getConfiguration(); + Dom dom = mojoExecution.getConfiguration().getDom(); PlexusConfiguration pomConfiguration; diff --git a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java index 9548cea9266f..5f9529383cae 100644 --- a/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java +++ b/maven-core/src/main/java/org/apache/maven/project/ProjectModelResolver.java @@ -305,4 +305,41 @@ public ModelSource resolveModel( final Dependency dependency, AtomicReference resolvedParent = new AtomicReference<>(); + ModelSource result = resolveModel( parent.getDelegate(), resolvedParent ); + if ( resolvedParent.get() != null ) + { + parent.setVersion( resolvedParent.get().getVersion() ); + } + return result; + } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException + { + AtomicReference resolvedDependency = new AtomicReference<>(); + ModelSource result = resolveModel( dependency.getDelegate(), resolvedDependency ); + if ( resolvedDependency.get() != null ) + { + dependency.setVersion( resolvedDependency.get().getVersion() ); + } + return result; + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException + { + addRepository( repository.getDelegate() ); + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository, boolean replace ) + throws InvalidRepositoryException + { + addRepository( repository.getDelegate(), replace ); + } } diff --git a/maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java b/maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java deleted file mode 100644 index 96bfb35d37c7..000000000000 --- a/maven-core/src/main/java/org/apache/maven/xml/internal/PlexusXmlBeanConverter.java +++ /dev/null @@ -1,488 +0,0 @@ -package org.apache.maven.xml.internal; - -/* - * 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. - */ - -import javax.annotation.Priority; -import javax.inject.Inject; - -import java.io.StringReader; -import java.lang.reflect.Array; -import java.lang.reflect.InvocationTargetException; -import java.util.ArrayList; -import java.util.Collection; -import java.util.HashMap; -import java.util.Map; -import java.util.Properties; - -import com.google.inject.Injector; -import com.google.inject.Key; -import com.google.inject.Module; -import com.google.inject.Singleton; -import com.google.inject.TypeLiteral; -import com.google.inject.spi.TypeConverter; -import com.google.inject.spi.TypeConverterBinding; -import org.apache.maven.api.xml.Dom; -import org.codehaus.plexus.util.xml.Xpp3Dom; -import org.codehaus.plexus.util.xml.Xpp3DomBuilder; -import org.codehaus.plexus.util.xml.pull.MXParser; -import org.codehaus.plexus.util.xml.pull.XmlPullParser; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.eclipse.sisu.bean.BeanProperties; -import org.eclipse.sisu.bean.BeanProperty; -import org.eclipse.sisu.inject.Logs; -import org.eclipse.sisu.inject.TypeArguments; -import org.eclipse.sisu.plexus.PlexusBeanConverter; -import org.eclipse.sisu.plexus.Roles; - -/** - * {@link PlexusBeanConverter} {@link Module} that converts Plexus XML configuration into beans. - */ -@Singleton -@Priority( 10 ) -public final class PlexusXmlBeanConverter - implements PlexusBeanConverter -{ - // ---------------------------------------------------------------------- - // Constants - // ---------------------------------------------------------------------- - - private static final String CONVERSION_ERROR = "Cannot convert: \"%s\" to: %s"; - - // ---------------------------------------------------------------------- - // Implementation fields - // ---------------------------------------------------------------------- - - private final Collection typeConverterBindings; - - // ---------------------------------------------------------------------- - // Constructors - // ---------------------------------------------------------------------- - - @Inject - PlexusXmlBeanConverter( final Injector injector ) - { - typeConverterBindings = injector.getTypeConverterBindings(); - } - - // ---------------------------------------------------------------------- - // Public methods - // ---------------------------------------------------------------------- - - @SuppressWarnings( { "unchecked", "rawtypes" } ) - public Object convert( final TypeLiteral role, final String value ) - { - if ( value.trim().startsWith( "<" ) ) - { - try - { - final MXParser parser = new MXParser(); - parser.setInput( new StringReader( value ) ); - parser.nextTag(); - - return parse( parser, role ); - } - catch ( final Exception e ) - { - throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, role ), e ); - } - } - - return convertText( value, role ); - } - - // ---------------------------------------------------------------------- - // Implementation methods - // ---------------------------------------------------------------------- - - /** - * Parses a sequence of XML elements and converts them to the given target type. - * - * @param parser The XML parser - * @param toType The target type - * @return Converted instance of the target type - */ - private Object parse( final MXParser parser, final TypeLiteral toType ) - throws Exception - { - parser.require( XmlPullParser.START_TAG, null, null ); - - final Class rawType = toType.getRawType(); - if ( Dom.class.isAssignableFrom( rawType ) ) - { - return org.apache.maven.internal.xml.Xpp3DomBuilder.build( parser ); - } - if ( Xpp3Dom.class.isAssignableFrom( rawType ) ) - { - return parseXpp3Dom( parser ); - } - if ( Properties.class.isAssignableFrom( rawType ) ) - { - return parseProperties( parser ); - } - if ( Map.class.isAssignableFrom( rawType ) ) - { - return parseMap( parser, TypeArguments.get( toType.getSupertype( Map.class ), 1 ) ); - } - if ( Collection.class.isAssignableFrom( rawType ) ) - { - return parseCollection( parser, TypeArguments.get( toType.getSupertype( Collection.class ), 0 ) ); - } - if ( rawType.isArray() ) - { - return parseArray( parser, TypeArguments.get( toType, 0 ) ); - } - return parseBean( parser, toType, rawType ); - } - - /** - * Parses an XML subtree and converts it to the {@link Xpp3Dom} type. - * - * @param parser The XML parser - * @return Converted Xpp3Dom instance - */ - private static Xpp3Dom parseXpp3Dom( final XmlPullParser parser ) - throws Exception - { - return Xpp3DomBuilder.build( parser ); - } - - /** - * Parses a sequence of XML elements and converts them to the appropriate {@link Properties} type. - * - * @param parser The XML parser - * @return Converted Properties instance - */ - private static Properties parseProperties( final XmlPullParser parser ) - throws Exception - { - final Properties properties = newImplementation( parser, Properties.class ); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - parser.nextTag(); - // 'name-then-value' or 'value-then-name' - if ( "name".equals( parser.getName() ) ) - { - final String name = parser.nextText(); - parser.nextTag(); - properties.put( name, parser.nextText() ); - } - else - { - final String value = parser.nextText(); - parser.nextTag(); - properties.put( parser.nextText(), value ); - } - parser.nextTag(); - } - return properties; - } - - /** - * Parses a sequence of XML elements and converts them to the appropriate {@link Map} type. - * - * @param parser The XML parser - * @return Converted Map instance - */ - private Map parseMap( final MXParser parser, final TypeLiteral toType ) - throws Exception - { - @SuppressWarnings( "unchecked" ) - final Map map = newImplementation( parser, HashMap.class ); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - map.put( parser.getName(), parse( parser, toType ) ); - } - return map; - } - - /** - * Parses a sequence of XML elements and converts them to the appropriate {@link Collection} type. - * - * @param parser The XML parser - * @return Converted Collection instance - */ - private Collection parseCollection( final MXParser parser, final TypeLiteral toType ) - throws Exception - { - @SuppressWarnings( "unchecked" ) - final Collection collection = newImplementation( parser, ArrayList.class ); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - collection.add( parse( parser, toType ) ); - } - return collection; - } - - /** - * Parses a sequence of XML elements and converts them to the appropriate array type. - * - * @param parser The XML parser - * @return Converted array instance - */ - private Object parseArray( final MXParser parser, final TypeLiteral toType ) - throws Exception - { - // convert to a collection first then convert that into an array - final Collection collection = parseCollection( parser, toType ); - final Object array = Array.newInstance( toType.getRawType(), collection.size() ); - - int i = 0; - for ( final Object element : collection ) - { - Array.set( array, i++, element ); - } - - return array; - } - - /** - * Parses a sequence of XML elements and converts them to the appropriate bean type. - * - * @param parser The XML parser - * @return Converted bean instance - */ - private Object parseBean( final MXParser parser, final TypeLiteral toType, final Class rawType ) - throws Exception - { - final Class clazz = loadImplementation( parseImplementation( parser ), rawType ); - - // simple bean? assumes string constructor - if ( parser.next() == XmlPullParser.TEXT ) - { - final String text = parser.getText(); - - // confirm element doesn't contain nested XML - if ( parser.next() != XmlPullParser.START_TAG ) - { - return convertText( text, clazz == rawType ? toType : TypeLiteral.get( clazz ) ); - } - } - - if ( String.class == clazz ) - { - // mimic plexus: discard any strings containing nested XML - while ( parser.getEventType() == XmlPullParser.START_TAG ) - { - final String pos = parser.getPositionDescription(); - Logs.warn( "Expected TEXT, not XML: {}", pos, new Throwable() ); - parser.skipSubTree(); - parser.nextTag(); - } - return ""; - } - - final Object bean = newImplementation( clazz ); - - // build map of all known bean properties belonging to the chosen implementation - final Map> propertyMap = new HashMap>(); - for ( final BeanProperty property : new BeanProperties( clazz ) ) - { - final String name = property.getName(); - if ( !propertyMap.containsKey( name ) ) - { - propertyMap.put( name, property ); - } - } - - while ( parser.getEventType() == XmlPullParser.START_TAG ) - { - // update properties inside the bean, guided by the cached property map - final BeanProperty property = propertyMap.get( Roles.camelizeName( parser.getName() ) ); - if ( property != null ) - { - property.set( bean, parse( parser, property.getType() ) ); - parser.nextTag(); - } - else - { - throw new XmlPullParserException( "Unknown bean property: " + parser.getName(), parser, null ); - } - } - - return bean; - } - - /** - * Parses an XML element looking for the name of a custom implementation. - * - * @param parser The XML parser - * @return Name of the custom implementation; otherwise {@code null} - */ - private static String parseImplementation( final XmlPullParser parser ) - { - return parser.getAttributeValue( null, "implementation" ); - } - - /** - * Attempts to load the named implementation, uses default implementation if no name is given. - * - * @param name The optional implementation name - * @param defaultClazz The default implementation type - * @return Custom implementation type if one was given; otherwise default implementation type - */ - private static Class loadImplementation( final String name, final Class defaultClazz ) - { - if ( null == name ) - { - return defaultClazz; // just use the default type - } - - // TCCL allows surrounding container to influence class loading policy - final ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - if ( tccl != null ) - { - try - { - return tccl.loadClass( name ); - } - catch ( final Exception e ) - { - // drop through... - } - catch ( final LinkageError e ) - { - // drop through... - } - } - - // assume custom type is in same class space as default - final ClassLoader peer = defaultClazz.getClassLoader(); - if ( peer != null ) - { - try - { - return peer.loadClass( name ); - } - catch ( final Exception e ) - { - // drop through... - } - catch ( final LinkageError e ) - { - // drop through... - } - } - - try - { - // last chance - classic model - return Class.forName( name ); - } - catch ( final Exception e ) - { - throw new TypeNotPresentException( name, e ); - } - catch ( final LinkageError e ) - { - throw new TypeNotPresentException( name, e ); - } - } - - /** - * Creates an instance of the given implementation using the default constructor. - * - * @param clazz The implementation type - * @return Instance of given implementation - */ - private static T newImplementation( final Class clazz ) - { - try - { - return clazz.newInstance(); - } - catch ( final Exception e ) - { - throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); - } - catch ( final LinkageError e ) - { - throw new IllegalArgumentException( "Cannot create instance of: " + clazz, e ); - } - } - - /** - * Creates an instance of the given implementation using the given string, assumes a public string constructor. - * - * @param clazz The implementation type - * @param value The string argument - * @return Instance of given implementation, constructed using the the given string - */ - private static T newImplementation( final Class clazz, final String value ) - { - try - { - return clazz.getConstructor( String.class ).newInstance( value ); - } - catch ( final Exception e ) - { - final Throwable cause = e instanceof InvocationTargetException ? e.getCause() : e; - throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), cause ); - } - catch ( final LinkageError e ) - { - throw new IllegalArgumentException( String.format( CONVERSION_ERROR, value, clazz ), e ); - } - } - - /** - * Creates an instance of the implementation named in the current XML element, or the default if no name is given. - * - * @param parser The XML parser - * @param defaultClazz The default implementation type - * @return Instance of custom implementation if one was given; otherwise instance of default type - */ - @SuppressWarnings( "unchecked" ) - private static T newImplementation( final XmlPullParser parser, final Class defaultClazz ) - { - return (T) newImplementation( loadImplementation( parseImplementation( parser ), defaultClazz ) ); - } - - /** - * Converts the given string to the target type, using {@link TypeConverter}s registered with the {@link Injector}. - * - * @param value The string value - * @param toType The target type - * @return Converted instance of the target type - */ - private Object convertText( final String value, final TypeLiteral toType ) - { - final String text = value.trim(); - - final Class rawType = toType.getRawType(); - if ( rawType.isAssignableFrom( String.class ) ) - { - return text; // compatible type => no conversion needed - } - - // use temporary Key as quick way to auto-box primitive types into their equivalent object types - final TypeLiteral boxedType = rawType.isPrimitive() ? Key.get( rawType ).getTypeLiteral() : toType; - - for ( final TypeConverterBinding b : typeConverterBindings ) - { - if ( b.getTypeMatcher().matches( boxedType ) ) - { - return b.getTypeConverter().convert( text, toType ); - } - } - - // last chance => attempt to create an instance of the expected type: use the string if non-empty - return text.length() == 0 ? newImplementation( rawType ) : newImplementation( rawType, text ); - } -} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java index 5e6e321466de..b3766b307da7 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java @@ -66,7 +66,7 @@ ModelSource resolveModel( String groupId, String artifactId, String version ) * * @see Parent#clone() */ - ModelSource resolveModel( Parent parent, AtomicReference modified ) + ModelSource resolveModel( org.apache.maven.model.Parent parent ) throws UnresolvableModelException; /** @@ -87,7 +87,7 @@ ModelSource resolveModel( Parent parent, AtomicReference modified ) * * @see Dependency#clone() */ - ModelSource resolveModel( Dependency dependency, AtomicReference modified ) + ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException; /** @@ -98,7 +98,7 @@ ModelSource resolveModel( Dependency dependency, AtomicReference mod * @param repository The repository to add to the internal search chain, must not be {@code null}. * @throws InvalidRepositoryException If the repository could not be added (e.g. due to invalid URL or layout). */ - void addRepository( Repository repository ) + void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException; /** @@ -112,7 +112,7 @@ void addRepository( Repository repository ) * @param repository The repository to add to the internal search chain, must not be {@code null}. * @throws InvalidRepositoryException If the repository could not be added (e.g. due to invalid URL or layout). */ - void addRepository( Repository repository, boolean replace ) + void addRepository( org.apache.maven.model.Repository repository, boolean replace ) throws InvalidRepositoryException; /** @@ -124,4 +124,15 @@ void addRepository( Repository repository, boolean replace ) */ ModelResolver newCopy(); + ModelSource resolveModel( Parent parent, AtomicReference modified ) + throws UnresolvableModelException; + + ModelSource resolveModel( Dependency dependency, AtomicReference modified ) + throws UnresolvableModelException; + + void addRepository( Repository repository ) + throws InvalidRepositoryException; + + void addRepository( Repository repository, boolean replace ) + throws InvalidRepositoryException; } diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java index c9319e39a4a4..defcaae25b3f 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java @@ -146,6 +146,32 @@ public ModelResolver newCopy() { return this; } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Parent parent ) throws UnresolvableModelException + { + return null; + } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) + throws UnresolvableModelException + { + return null; + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException + { + + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository, boolean replace ) + throws InvalidRepositoryException + { + + } } @Test diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java index 595a7e7056a9..e2bb7a5bc2e8 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultModelResolver.java @@ -283,4 +283,41 @@ public ModelSource resolveModel( final Dependency dependency, AtomicReference resolvedParent = new AtomicReference<>(); + ModelSource result = resolveModel( parent.getDelegate(), resolvedParent ); + if ( resolvedParent.get() != null ) + { + parent.setVersion( resolvedParent.get().getVersion() ); + } + return result; + } + + @Override + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException + { + AtomicReference resolvedDependency = new AtomicReference<>(); + ModelSource result = resolveModel( dependency.getDelegate(), resolvedDependency ); + if ( resolvedDependency.get() != null ) + { + dependency.setVersion( resolvedDependency.get().getVersion() ); + } + return result; + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository ) throws InvalidRepositoryException + { + addRepository( repository.getDelegate() ); + } + + @Override + public void addRepository( org.apache.maven.model.Repository repository, boolean replace ) + throws InvalidRepositoryException + { + addRepository( repository.getDelegate(), replace ); + } } From 900c8afd7c5247c880ee739406fd20d0cd9961bf Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 4 Apr 2022 10:44:00 +0200 Subject: [PATCH 14/98] Remove advertisement of unchecked exceptions in the methods --- .../java/org/apache/maven/api/Artifact.java | 2 +- .../java/org/apache/maven/api/Dependency.java | 1 - .../main/java/org/apache/maven/api/Event.java | 4 +- .../org/apache/maven/api/LocalRepository.java | 3 + .../org/apache/maven/api/MetadataStorage.java | 4 +- .../java/org/apache/maven/api/Project.java | 11 ++-- .../java/org/apache/maven/api/Session.java | 59 ++++++++++------- .../org/apache/maven/api/SessionData.java | 5 +- .../org/apache/maven/api/plugin/Mojo.java | 3 +- .../maven/api/services/ArtifactDeployer.java | 22 +++---- .../api/services/ArtifactDeployerRequest.java | 12 ++-- .../maven/api/services/ArtifactFactory.java | 24 +++++-- .../api/services/ArtifactFactoryRequest.java | 4 ++ .../maven/api/services/ArtifactInstaller.java | 19 +++--- .../services/ArtifactInstallerRequest.java | 8 ++- .../maven/api/services/ArtifactManager.java | 4 +- .../maven/api/services/ArtifactResolver.java | 12 ++-- .../api/services/ArtifactResolverRequest.java | 8 ++- .../maven/api/services/BaseRequest.java | 15 ++--- .../api/services/DependencyCollector.java | 10 +-- .../services/DependencyCollectorRequest.java | 63 ++++++++++++------- .../maven/api/services/DependencyFactory.java | 18 ++++-- .../services/DependencyFactoryRequest.java | 4 ++ .../api/services/DependencyResolver.java | 37 +++++------ .../services/DependencyResolverRequest.java | 31 +++++---- .../maven/api/services/ProjectBuilder.java | 41 ++++++++++-- .../api/services/ProjectBuilderRequest.java | 18 ++++-- .../maven/api/services/RepositoryFactory.java | 10 ++- .../maven/api/services/ResolutionScope.java | 1 + .../maven/api/services/ToolchainManager.java | 32 +++++++++- .../api/services/xml/XmlReaderRequest.java | 7 +++ .../maven/api/annotations/Immutable.java | 1 + .../maven/api/annotations/NotThreadSafe.java} | 24 +++---- api/maven-api-model/src/main/mdo/model.vm | 18 +++++- .../maven/internal/impl/DefaultArtifact.java | 13 ++-- .../impl/DefaultArtifactDeployer.java | 27 +++++--- .../internal/impl/DefaultArtifactFactory.java | 13 ++-- .../impl/DefaultArtifactInstaller.java | 45 +++---------- .../impl/DefaultArtifactResolver.java | 11 ++-- .../internal/impl/DefaultDependency.java | 7 ++- .../impl/DefaultDependencyCollector.java | 7 ++- .../impl/DefaultDependencyFactory.java | 14 +++-- .../internal/impl/DefaultLocalRepository.java | 8 ++- .../internal/impl/DefaultModelXmlFactory.java | 9 +-- .../maven/internal/impl/DefaultNode.java | 9 +-- .../maven/internal/impl/DefaultProject.java | 9 ++- .../maven/internal/impl/DefaultSession.java | 20 +++--- .../org/apache/maven/internal/impl/Utils.java | 31 ++++++--- 48 files changed, 471 insertions(+), 287 deletions(-) rename api/{maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java => maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java} (67%) rename api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java => maven-core/src/main/java/org/apache/maven/internal/impl/Utils.java (55%) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index 98ed400cbb1c..a336bdd5fb02 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -26,7 +26,7 @@ import java.util.Optional; /** - * TODO: split between Coordinates / AttachedArtifact / ResolvedArtifact + * TODO: split between Coordinates / AttachedArtifact / ResolvedArtifact ? */ @Immutable public interface Artifact diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java index ea208bfcfbdc..1dde0f9826e0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -31,7 +31,6 @@ public interface Dependency @Nonnull Artifact getArtifact(); - // TODO: make that en enum ? @Nonnull String getScope(); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java index 088e8852a056..b606baba4a85 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java @@ -24,7 +24,9 @@ import java.util.Optional; /** - * Event + * Event sent by maven during various phases of the build process. + * Such events can be listened to using {@link Listener}s objects + * registered in the {@link Session}. */ public interface Event { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java index d1135673dcb0..5738af40adce 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java @@ -21,9 +21,12 @@ import java.nio.file.Path; +import org.apache.maven.api.annotations.Nonnull; + public interface LocalRepository extends Repository { + @Nonnull Path getPath(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java index 40e6d509786e..ed667243ba85 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java @@ -24,5 +24,7 @@ */ public enum MetadataStorage { - Group, Artifact, Version + GROUP, + ARTIFACT, + VERSION } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java index 80352c8a3c31..6ebd95f0bddd 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -23,6 +23,7 @@ import java.nio.file.Path; import java.util.List; +import java.util.Optional; import org.apache.maven.api.model.Model; @@ -57,12 +58,13 @@ public interface Project * will not point to an actual pom file. * @return the path of the pom */ - Path getPomPath(); + @Nonnull + Optional getPomPath(); - default Path getBasedir() + @Nonnull + default Optional getBasedir() { - Path pomPath = getPomPath(); - return pomPath != null ? pomPath.getParent() : null; + return getPomPath().map( Path::getParent ); } @Nonnull @@ -71,6 +73,7 @@ default Path getBasedir() @Nonnull List getManagedDependencies(); + @Nonnull default String getId() { return getModel().getId(); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index 3de3372ac938..2aa678aacf38 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -34,7 +34,6 @@ import org.apache.maven.api.services.ArtifactDeployer; import org.apache.maven.api.services.ArtifactDeployerException; import org.apache.maven.api.services.ArtifactFactory; -import org.apache.maven.api.services.ArtifactFactoryException; import org.apache.maven.api.services.ArtifactInstaller; import org.apache.maven.api.services.ArtifactInstallerException; import org.apache.maven.api.services.ArtifactManager; @@ -85,13 +84,14 @@ public interface Session * @throws NoSuchElementException if the service could not be found */ @Nonnull - T getService( Class clazz ) throws NoSuchElementException; + T getService( Class clazz ); /** * Creates a derived session using the given local repository. * * @param localRepository the new local repository * @return the derived session + * @throws NullPointerException if {@code localRepository} is null */ @Nonnull Session withLocalRepository( @Nonnull LocalRepository localRepository ); @@ -101,6 +101,7 @@ public interface Session * * @param repositories the new list of remote repositories * @return the derived session + * @throws NullPointerException if {@code repositories} is null */ @Nonnull Session withRemoteRepositories( @Nonnull List repositories ); @@ -109,6 +110,7 @@ public interface Session * Register the given listener which will receive all events. * * @param listener the listener to register + * @throws NullPointerException if {@code listener} is null */ void registerListener( @Nonnull Listener listener ); @@ -116,13 +118,14 @@ public interface Session * Unregisters a previously registered listener. * * @param listener the listener to unregister + * @throws NullPointerException if {@code listener} is null */ void unregisterListener( @Nonnull Listener listener ); /** * Returns the list of registered listeners. * - * @return an immutable collection of listeners + * @return an immutable collection of listeners, never {@code null} */ @Nonnull Collection getListeners(); @@ -132,7 +135,6 @@ public interface Session * @see RepositoryFactory#createLocal(Path) */ default LocalRepository createLocalRepository( Path path ) - throws ArtifactFactoryException, IllegalArgumentException { return getService( RepositoryFactory.class ).createLocal( path ); } @@ -164,7 +166,6 @@ default RemoteRepository createRemoteRepository( @Nonnull Repository repository * @see ArtifactFactory#create(Session, String, String, String, String) */ default Artifact createArtifact( String groupId, String artifactId, String version, String extension ) - throws ArtifactFactoryException, IllegalArgumentException { return getService( ArtifactFactory.class ) .create( this, groupId, artifactId, version, extension ); @@ -176,7 +177,6 @@ default Artifact createArtifact( String groupId, String artifactId, String versi */ default Artifact createArtifact( String groupId, String artifactId, String version, String classifier, String extension, String type ) - throws ArtifactFactoryException, IllegalArgumentException { return getService( ArtifactFactory.class ) .create( this, groupId, artifactId, version, classifier, extension, type ); @@ -185,30 +185,33 @@ default Artifact createArtifact( String groupId, String artifactId, String versi /** * Shortcut for getService(ArtifactResolver.class).resolve(...) * @see ArtifactResolver#resolve(Session, Artifact) + * + * @throws ArtifactResolverException if the artifact resolution failed */ default ArtifactResolverResult resolveArtifact( Artifact artifact ) - throws ArtifactResolverException, IllegalArgumentException { return getService( ArtifactResolver.class ) .resolve( this, artifact ); } /** - * Shortcut for getService(ArtifactInstaller.class).install(...) + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} * @see ArtifactInstaller#install(Session, Collection) + * + * @throws ArtifactInstallerException if the artifacts installation failed */ default void installArtifacts( Artifact... artifacts ) - throws ArtifactInstallerException, IllegalArgumentException { installArtifacts( Arrays.asList( artifacts ) ); } /** - * Shortcut for getService(ArtifactInstaller.class).install(...) + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} * @see ArtifactInstaller#install(Session, Collection) + * + * @throws ArtifactInstallerException if the artifacts installation failed */ default void installArtifacts( Collection artifacts ) - throws ArtifactInstallerException, IllegalArgumentException { getService( ArtifactInstaller.class ) .install( this, artifacts ); @@ -217,9 +220,10 @@ default void installArtifacts( Collection artifacts ) /** * Shortcut for getService(ArtifactDeployer.class).deploy(...) * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection) + * + * @throws ArtifactDeployerException if the artifacts deployment failed */ default void deployArtifact( RemoteRepository repository, Artifact... artifacts ) - throws ArtifactDeployerException, IllegalArgumentException { getService( ArtifactDeployer.class ) .deploy( this, repository, Arrays.asList( artifacts ) ); @@ -229,7 +233,7 @@ default void deployArtifact( RemoteRepository repository, Artifact... artifacts * Shortcut for getService(ArtifactManager.class).setPath(...) * @see ArtifactManager#setPath(Artifact, Path) */ - default void setArtifactPath( @Nonnull Artifact artifact, Path path ) + default void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ) { getService( ArtifactManager.class ) .setPath( artifact, path ); @@ -260,7 +264,8 @@ default boolean isVersionSnapshot( @Nonnull String version ) * Shortcut for getService(DependencyFactory.class).create(...) * @see DependencyFactory#create(Session, Artifact) */ - default Dependency createDependency( Artifact artifact ) + @Nonnull + default Dependency createDependency( @Nonnull Artifact artifact ) { return getService( DependencyFactory.class ) .create( this, artifact ); @@ -269,9 +274,11 @@ default Dependency createDependency( Artifact artifact ) /** * Shortcut for getService(DependencyCollector.class).collect(...) * @see DependencyCollector#collect(Session, Artifact) + * + * @throws DependencyCollectorException if the dependency collection failed */ - default DependencyCollectorResult collectDependencies( Artifact artifact ) - throws DependencyCollectorException, IllegalArgumentException + @Nonnull + default DependencyCollectorResult collectDependencies( @Nonnull Artifact artifact ) { return getService( DependencyCollector.class ) .collect( this, artifact ); @@ -280,9 +287,11 @@ default DependencyCollectorResult collectDependencies( Artifact artifact ) /** * Shortcut for getService(DependencyCollector.class).collect(...) * @see DependencyCollector#collect(Session, Project) + * + * @throws DependencyCollectorException if the dependency collection failed */ - default DependencyCollectorResult collectDependencies( Project project ) - throws DependencyCollectorException, IllegalArgumentException + @Nonnull + default DependencyCollectorResult collectDependencies( @Nonnull Project project ) { return getService( DependencyCollector.class ) .collect( this, project ); @@ -291,9 +300,11 @@ default DependencyCollectorResult collectDependencies( Project project ) /** * Shortcut for getService(DependencyCollector.class).collect(...) * @see DependencyCollector#collect(Session, Dependency) + * + * @throws DependencyCollectorException if the dependency collection failed */ - default DependencyCollectorResult collectDependencies( Dependency dependency ) - throws DependencyCollectorException, IllegalArgumentException + @Nonnull + default DependencyCollectorResult collectDependencies( @Nonnull Dependency dependency ) { return getService( DependencyCollector.class ) .collect( this, dependency ); @@ -302,15 +313,17 @@ default DependencyCollectorResult collectDependencies( Dependency dependency ) /** * Shortcut for getService(DependencyResolver.class).resolve(...) * @see DependencyResolver#resolve(Session, Dependency, Predicate) + * + * @throws DependencyResolverException if the dependency resolution failed */ - default DependencyResolverResult resolveDependencies( Dependency dependency ) - throws DependencyResolverException, IllegalArgumentException + @Nonnull + default DependencyResolverResult resolveDependencies( @Nonnull Dependency dependency ) { return getService( DependencyResolver.class ) .resolve( this, dependency, null ); } - default Path getPathForLocalArtifact( Artifact artifact ) + default Path getPathForLocalArtifact( @Nonnull Artifact artifact ) { return getService( LocalRepositoryManager.class ) .getPathForLocalArtifact( this, getLocalRepository(), artifact ); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java index 7b1b9c32ec2a..56f0289510ac 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java @@ -21,6 +21,7 @@ import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.Provider; import org.apache.maven.api.annotations.ThreadSafe; import java.util.function.Supplier; @@ -35,10 +36,8 @@ * Note: Actual implementations must be thread-safe. * * @see Session#getData() - * @noimplement This interface is not intended to be implemented by clients. - * @noextend This interface is not intended to be extended by clients. */ -@ThreadSafe +@ThreadSafe @Provider public interface SessionData { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java index 04dae3752e11..593c29cf9997 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java @@ -39,7 +39,6 @@ public interface Mojo * * @throws MojoException if a problem occurs. */ - void execute() - throws MojoException; + void execute(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java index c78f1ad491e2..1156c028235d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java @@ -24,6 +24,7 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Nonnull; /** * @@ -33,27 +34,20 @@ public interface ArtifactDeployer extends Service /** * @param request {@link ArtifactDeployerRequest} - * @throws ArtifactDeployerException in case of an error. - * @throws IllegalArgumentException in case of parameter request is null or parameter - * mavenArtifacts is null or mavenArtifacts.isEmpty() is - * true. + * @throws ArtifactDeployerException if the deployment failed */ - void deploy( ArtifactDeployerRequest request ) - throws ArtifactDeployerException, IllegalArgumentException; + void deploy( @Nonnull ArtifactDeployerRequest request ); /** * @param session the repository session * @param repository the repository to deploy to * @param artifacts the collection of artifacts to deploy - * @throws ArtifactDeployerException in case of an error. - * @throws IllegalArgumentException in case of parameter request is null or parameter - * artifacts is null or artifacts.isEmpty() is - * true. + * @throws ArtifactDeployerException if the deployment failed + * @throws IllegalArgumentException if an argument is {@code null} or invalid */ - default void deploy( Session session, - RemoteRepository repository, - Collection artifacts ) - throws ArtifactDeployerException, IllegalArgumentException + default void deploy( @Nonnull Session session, + @Nonnull RemoteRepository repository, + @Nonnull Collection artifacts ) { deploy( ArtifactDeployerRequest.build( session, repository, artifacts ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java index 84a78a538e7b..4ac697459092 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java @@ -27,6 +27,8 @@ import org.apache.maven.api.Artifact; import org.apache.maven.api.RemoteRepository; +import static org.apache.maven.api.services.BaseRequest.nonNull; + /** * A request for deploying one or more artifacts to a remote repository. */ @@ -51,10 +53,12 @@ static ArtifactDeployerRequestBuilder builder() } @Nonnull - static ArtifactDeployerRequest build( Session session, RemoteRepository repository, Collection artifacts ) + static ArtifactDeployerRequest build( @Nonnull Session session, + @Nonnull RemoteRepository repository, + @Nonnull Collection artifacts ) { return builder() - .session( session ) + .session( nonNull( session, "session can not be null" ) ) .repository( repository ) .artifacts( artifacts ) .build(); @@ -113,8 +117,8 @@ private static class DefaultArtifactDeployerRequest extends BaseRequest int retryFailedDeploymentCount ) { super( session ); - this.repository = requireNonNull( repository, "repository" ); - this.artifacts = unmodifiable( artifacts, "artifacts" ); + this.repository = nonNull( repository, "repository can not be null" ); + this.artifacts = nonNull( artifacts, "artifacts can not be null" ); this.retryFailedDeploymentCount = retryFailedDeploymentCount; } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java index c581a97ce1d4..8a46f42a5e0d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java @@ -21,22 +21,34 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Nonnull; +/** + * Service used to create {@link Artifact} objects. + */ public interface ArtifactFactory extends Service { - Artifact create( ArtifactFactoryRequest request ) - throws ArtifactFactoryException, IllegalArgumentException; + /** + * Creates an artifact. + * + * @param request the request holding artifact creation parameters + * @return an {@code Artifact}, never {@code null} + * @throws IllegalArgumentException if {@code request} is null or {@code request.session} is null or invalid + */ + @Nonnull + Artifact create( @Nonnull ArtifactFactoryRequest request ); - default Artifact create( Session session, String groupId, String artifactId, String version, String extension ) - throws ArtifactFactoryException, IllegalArgumentException + @Nonnull + default Artifact create( @Nonnull Session session, String groupId, + String artifactId, String version, String extension ) { return create( ArtifactFactoryRequest.build( session, groupId, artifactId, version, extension ) ); } - default Artifact create( Session session, String groupId, String artifactId, String version, + @Nonnull + default Artifact create( @Nonnull Session session, String groupId, String artifactId, String version, String classifier, String extension, String type ) - throws ArtifactFactoryException, IllegalArgumentException { return create( ArtifactFactoryRequest.build( session, groupId, artifactId, version, classifier, extension, type ) ); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java index 82cc44aed927..e48d59900c7e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java @@ -19,10 +19,13 @@ * under the License. */ +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.NotThreadSafe; +@Immutable public interface ArtifactFactoryRequest { @@ -72,6 +75,7 @@ static ArtifactFactoryRequestBuilder builder() return new ArtifactFactoryRequestBuilder(); } + @NotThreadSafe class ArtifactFactoryRequestBuilder { private Session session; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java index b440a2818815..0cafa236369d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java @@ -33,21 +33,19 @@ public interface ArtifactInstaller extends Service /** * @param request {@link ArtifactInstallerRequest} * @throws ArtifactInstallerException in case of an error. - * @throws IllegalArgumentException in case request is null. + * @throws IllegalArgumentException in case {@code request} is {@code null}. */ - void install( ArtifactInstallerRequest request ) - throws ArtifactInstallerException, IllegalArgumentException; + void install( ArtifactInstallerRequest request ); /** * @param session the repository session * @param artifact the {@link Artifact} to install * @throws ArtifactInstallerException In case of an error which can be the a given artifact can not be found or the * installation has failed. - * @throws IllegalArgumentException in case of parameter session is null or - * artifact is null. + * @throws IllegalArgumentException in case of parameter {@code session} is {@code null} or + * {@code artifact} is {@code null}. */ default void install( Session session, Artifact artifact ) - throws ArtifactInstallerException, IllegalArgumentException { install( session, Collections.singletonList( artifact ) ); } @@ -57,13 +55,12 @@ default void install( Session session, Artifact artifact ) * @param artifacts Collection of {@link Artifact MavenArtifacts} * @throws ArtifactInstallerException In case of an error which can be the a given artifact can not be found or the * installation has failed. - * @throws IllegalArgumentException in case of parameter request is null or parameter - * localRepository is null or localRepository is not a directory - * or parameter mavenArtifacts is null or - * mavenArtifacts.isEmpty() is true. + * @throws IllegalArgumentException in case of parameter {@code request} is {@code null} or parameter + * {@code localRepository} is {@code null} or {@code localRepository} is not a directory + * or parameter {@code mavenArtifacts} is {@code null} or + * {@code mavenArtifacts.isEmpty()} is {@code true}. */ default void install( Session session, Collection artifacts ) - throws ArtifactInstallerException { install( ArtifactInstallerRequest.build( session, artifacts ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java index 9a62a2261321..8a6847acf25e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java @@ -19,7 +19,9 @@ * under the License. */ +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; import org.apache.maven.api.annotations.Nullable; import java.util.Collection; @@ -31,6 +33,7 @@ /** * A request for installing one or more artifacts in the local repository. */ +@Immutable public interface ArtifactInstallerRequest { @@ -40,11 +43,13 @@ public interface ArtifactInstallerRequest @Nonnull Collection getArtifacts(); + @Nonnull static ArtifactInstallerRequestBuilder builder() { return new ArtifactInstallerRequestBuilder(); } + @Nonnull static ArtifactInstallerRequest build( Session session, Collection artifacts ) { return builder() @@ -53,6 +58,7 @@ static ArtifactInstallerRequest build( Session session, Collection art .build(); } + @NotThreadSafe class ArtifactInstallerRequestBuilder { Session session; @@ -88,7 +94,7 @@ static class DefaultArtifactInstallerRequest extends BaseRequest @Nonnull Collection artifacts ) { super( session ); - this.artifacts = unmodifiable( artifacts, "artifacts" ); + this.artifacts = nonNull( artifacts, "artifacts can not be null" ); } @Nonnull diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java index cf9e211eb686..e5d90a832020 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java @@ -33,7 +33,7 @@ public interface ArtifactManager extends Service /** * Returns the path of the file previously associated to this artifact - * or Optional.empty() if no path has been associated. + * or {@code Optional.empty()} if no path has been associated. */ @Nonnull Optional getPath( @Nonnull Artifact artifact ); @@ -55,7 +55,7 @@ public interface ArtifactManager extends Service void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metadata ); /** - * Checks whether a given artifact version is considered a SNAPSHOT or not. + * Checks whether a given artifact version is considered a {@code SNAPSHOT} or not. */ boolean isSnapshot( String version ); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java index 25b6d133c8f0..272a0375b0d4 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -32,23 +32,21 @@ public interface ArtifactResolver extends Service * @param request {@link ArtifactResolverRequest} * @return {@link ArtifactResolverResult} * @throws ArtifactResolverException in case of an error. - * @throws NullPointerException in case of parameter buildingRequest is null or - * parameter mavenArtifact is null. + * @throws IllegalArgumentException in case of parameter {@code buildingRequest} is {@code null} or + * parameter {@code mavenArtifact} is {@code null} or invalid. */ - ArtifactResolverResult resolve( ArtifactResolverRequest request ) - throws ArtifactResolverException, IllegalArgumentException; + ArtifactResolverResult resolve( ArtifactResolverRequest request ); /** * @param session {@link Session} * @param artifact {@link Artifact} * @return {@link ArtifactResolverResult} * @throws ArtifactResolverException in case of an error. - * @throws NullPointerException in case of parameter buildingRequest is null or - * parameter coordinate is null. + * @throws IllegalArgumentException in case of parameter {@code buildingRequest} is {@code null} or + * parameter {@code coordinate} is {@code null} or invalid. */ default ArtifactResolverResult resolve( Session session, Artifact artifact ) - throws ArtifactResolverException, IllegalArgumentException { return resolve( ArtifactResolverRequest.build( session, artifact ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java index 16bfee844221..1d163889c88e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java @@ -19,16 +19,17 @@ * under the License. */ +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; -import java.util.Objects; - import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.NotThreadSafe; /** * A request for resolving an artifact. */ +@Immutable public interface ArtifactResolverRequest { @Nonnull @@ -52,6 +53,7 @@ static ArtifactResolverRequest build( Session session, Artifact artifact ) .build(); } + @NotThreadSafe class ArtifactResolverRequestBuilder { Session session; @@ -86,7 +88,7 @@ private static class DefaultArtifactResolverRequest extends BaseRequest implemen @Nonnull Artifact artifact ) { super( session ); - this.artifact = Objects.requireNonNull( artifact ); + this.artifact = nonNull( artifact, "artifact can not be null" ); } @Nonnull diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java index 515257adeb10..dd8b1046e359 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java @@ -37,7 +37,7 @@ abstract class BaseRequest protected BaseRequest( @Nonnull Session session ) { - this.session = requireNonNull( session, "session" ); + this.session = nonNull( session, "session can not be null" ); } @Nonnull @@ -46,21 +46,18 @@ public Session getSession() return session; } - public static T requireNonNull( T obj, String message ) + public static T nonNull( T obj, String message ) { if ( obj == null ) { - throw new IllegalArgumentException( message + " must mot be null" ); + throw new IllegalArgumentException( message ); } return obj; } - protected static Collection unmodifiable( Collection obj, String message ) + protected static Collection unmodifiable( Collection obj ) { - if ( requireNonNull( obj, message ).isEmpty() ) - { - throw new IllegalArgumentException( message + " must not be empty" ); - } - return Collections.unmodifiableCollection( new ArrayList<>( obj ) ); + return obj != null && !obj.isEmpty() + ? Collections.unmodifiableCollection( new ArrayList<>( obj ) ) : Collections.emptyList(); } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java index 2d222b76a299..e802eff211fb 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java @@ -46,14 +46,14 @@ public interface DependencyCollector extends Service * @param request The dependency collection request, must not be {@code null}. * @return The collection result, never {@code null}. * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid * * @see DependencyCollector#collect(Session, Project) * @see DependencyCollector#collect(Session, Dependency) * @see DependencyCollector#collect(Session, Artifact) */ @Nonnull - DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ) - throws DependencyCollectorException, IllegalArgumentException; + DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ); /** * Collects the transitive dependencies of some artifacts and builds a dependency graph. Note that this operation is @@ -64,12 +64,12 @@ DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ) * @param root The Maven Dependency, must not be {@code null}. * @return The collection result, never {@code null}. * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid * @see #collect(DependencyCollectorRequest) */ @Nonnull default DependencyCollectorResult collect( @Nonnull Session session, @Nonnull Dependency root ) - throws DependencyCollectorException { return collect( DependencyCollectorRequest.build( session, root ) ); } @@ -83,12 +83,12 @@ default DependencyCollectorResult collect( @Nonnull Session session, * @param project The {@link Project}, must not be {@code null}. * @return The collection result, never {@code null}. * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid * @see #collect(DependencyCollectorRequest) */ @Nonnull default DependencyCollectorResult collect( @Nonnull Session session, @Nonnull Project project ) - throws DependencyCollectorException { return collect( DependencyCollectorRequest.build( session, project ) ); } @@ -102,12 +102,12 @@ default DependencyCollectorResult collect( @Nonnull Session session, * @param artifact The {@link Artifact}, must not be {@code null}. * @return The collection result, never {@code null}. * @throws DependencyCollectorException If the dependency tree could not be built. + * @throws IllegalArgumentException if an argument is null or invalid * @see #collect(DependencyCollectorRequest) */ @Nonnull default DependencyCollectorResult collect( @Nonnull Session session, @Nonnull Artifact artifact ) - throws DependencyCollectorException { return collect( DependencyCollectorRequest.build( session, artifact ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java index b2ff8d169615..02413590afcd 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import java.util.ArrayList; @@ -31,6 +32,10 @@ import org.apache.maven.api.Project; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.NotThreadSafe; +import org.apache.maven.api.annotations.Nullable; + +import static org.apache.maven.api.services.BaseRequest.nonNull; /** * A request to collect the transitive dependencies and to build a dependency graph from them. There are three ways to @@ -41,6 +46,7 @@ * * @see DependencyCollector#collect(DependencyCollectorRequest) */ +@Immutable public interface DependencyCollectorRequest { @@ -59,26 +65,29 @@ public interface DependencyCollectorRequest @Nonnull Collection getManagedDependencies(); - static DependencyCollectorRequest build( Session session, Artifact root ) + @Nonnull + static DependencyCollectorRequest build( @Nonnull Session session, Artifact root ) { - BaseRequest.requireNonNull( session, "session" ); return builder() - .session( session ) - .root( session.createDependency( root ) ) + .session( nonNull( session, "session can not be null" ) ) + .root( session.createDependency( nonNull( root, "root can not be null" ) ) ) .build(); } - static DependencyCollectorRequest build( Session session, Dependency root ) + @Nonnull + static DependencyCollectorRequest build( @Nonnull Session session, @Nonnull Dependency root ) { return builder() - .session( session ) - .root( root ) + .session( nonNull( session, "session can not be null" ) ) + .root( nonNull( root, "root can not be null" ) ) .build(); } - static DependencyCollectorRequest build( Session session, Project project ) + @Nonnull + static DependencyCollectorRequest build( @Nonnull Session session, @Nonnull Project project ) { - BaseRequest.requireNonNull( session, "session" ); + nonNull( session, "session can not be null" ); + nonNull( project, "project can not be null" ); return builder() .session( session ) .root( session.createDependency( project.getArtifact() ) ) @@ -87,11 +96,13 @@ static DependencyCollectorRequest build( Session session, Project project ) .build(); } + @Nonnull static DependencyCollectorRequestBuilder builder() { return new DependencyCollectorRequestBuilder(); } + @NotThreadSafe class DependencyCollectorRequestBuilder { @@ -120,7 +131,7 @@ public DependencyCollectorRequestBuilder session( @Nonnull Session session ) * @return This request for chaining, never {@code null}. */ @Nonnull - public DependencyCollectorRequestBuilder rootArtifact( Artifact rootArtifact ) + public DependencyCollectorRequestBuilder rootArtifact( @Nullable Artifact rootArtifact ) { this.rootArtifact = rootArtifact; return this; @@ -146,7 +157,7 @@ public DependencyCollectorRequestBuilder root( @Nonnull Dependency root ) * @return This request for chaining, never {@code null}. */ @Nonnull - public DependencyCollectorRequestBuilder dependencies( List dependencies ) + public DependencyCollectorRequestBuilder dependencies( @Nullable List dependencies ) { this.dependencies = ( dependencies != null ) ? dependencies : Collections.emptyList(); return this; @@ -158,7 +169,8 @@ public DependencyCollectorRequestBuilder dependencies( List dependen * @param dependency The dependency to add, may be {@code null}. * @return This request for chaining, never {@code null}. */ - public DependencyCollectorRequestBuilder dependency( Dependency dependency ) + @Nonnull + public DependencyCollectorRequestBuilder dependency( @Nullable Dependency dependency ) { if ( dependency != null ) { @@ -180,7 +192,8 @@ public DependencyCollectorRequestBuilder dependency( Dependency dependency ) * @param managedDependencies The dependency management, may be {@code null}. * @return This request for chaining, never {@code null}. */ - public DependencyCollectorRequestBuilder managedDependencies( List managedDependencies ) + @Nonnull + public DependencyCollectorRequestBuilder managedDependencies( @Nullable List managedDependencies ) { this.managedDependencies = ( managedDependencies != null ) ? managedDependencies : Collections.emptyList(); return this; @@ -189,10 +202,12 @@ public DependencyCollectorRequestBuilder managedDependencies( List m /** * Adds the specified managed dependency. * - * @param managedDependency The managed dependency to add, may be {@code null}. + * @param managedDependency The managed dependency to add, may be {@code null} in which case the call + * will have no effect. * @return This request for chaining, never {@code null}. */ - public DependencyCollectorRequestBuilder managedDependency( Dependency managedDependency ) + @Nonnull + public DependencyCollectorRequestBuilder managedDependency( @Nullable Dependency managedDependency ) { if ( managedDependency != null ) { @@ -205,6 +220,7 @@ public DependencyCollectorRequestBuilder managedDependency( Dependency managedDe return this; } + @Nonnull public DependencyCollectorRequest build() { return new DefaultDependencyCollectorRequest( @@ -232,19 +248,17 @@ static class DefaultDependencyCollectorRequest extends BaseRequest * null}. */ DefaultDependencyCollectorRequest( - Session session, - Artifact rootArtifact, - Dependency root, - Collection dependencies, - Collection managedDependencies ) + @Nonnull Session session, + @Nullable Artifact rootArtifact, + @Nullable Dependency root, + @Nonnull Collection dependencies, + @Nonnull Collection managedDependencies ) { super( session ); this.rootArtifact = rootArtifact; this.root = root; - this.dependencies = dependencies != null && !dependencies.isEmpty() - ? unmodifiable( dependencies, "dependencies" ) : Collections.emptyList(); - this.managedDependencies = managedDependencies != null && !managedDependencies.isEmpty() - ? unmodifiable( managedDependencies, "managedDependencies" ) : Collections.emptyList(); + this.dependencies = unmodifiable( dependencies ); + this.managedDependencies = unmodifiable( managedDependencies ); } @@ -276,6 +290,7 @@ public Collection getManagedDependencies() return managedDependencies; } + @Nonnull @Override public String toString() { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java index 50e5849616f0..ffcdb24a275f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java @@ -22,15 +22,25 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; +import org.apache.maven.api.annotations.Nonnull; public interface DependencyFactory extends Service { - Dependency create( DependencyFactoryRequest request ) - throws DependencyFactoryException, IllegalArgumentException; + /** + * Creates a new {@link Dependency} object from the request. + * + * @param request the request containing the various data + * @return a new {@link Dependency} object. + * + * @throws IllegalArgumentException if {@code request} is null or + * if {@code request.getSession()} is null or invalid + */ + @Nonnull + Dependency create( @Nonnull DependencyFactoryRequest request ); - default Dependency create( Session session, Artifact artifact ) - throws DependencyFactoryException, IllegalArgumentException + @Nonnull + default Dependency create( @Nonnull Session session, @Nonnull Artifact artifact ) { return create( DependencyFactoryRequest.build( session, artifact ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java index eafac2eb8704..bbd501f7011a 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import java.util.ArrayList; @@ -28,7 +29,9 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.Exclusion; +import org.apache.maven.api.annotations.NotThreadSafe; +@Immutable public interface DependencyFactoryRequest { @@ -57,6 +60,7 @@ static DependencyFactoryRequestBuilder builder() return new DependencyFactoryRequestBuilder(); } + @NotThreadSafe class DependencyFactoryRequestBuilder { private Session session; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java index c4549d5bbcea..de8d02186812 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java @@ -19,13 +19,14 @@ * under the License. */ -import java.util.List; import java.util.function.Predicate; import org.apache.maven.api.Session; import org.apache.maven.api.Dependency; import org.apache.maven.api.Node; import org.apache.maven.api.Project; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; /** * The DependencyResolver service can be used to collect the dependencies @@ -42,15 +43,12 @@ public interface DependencyResolver extends Service * @param request {@link DependencyResolverRequest} * @return the resolved dependencies. * @throws DependencyResolverException in case of an error. + * @throws IllegalArgumentException if {@code request} is null or invalid */ - DependencyResolverResult resolve( DependencyResolverRequest request ) - throws DependencyResolverException; + DependencyResolverResult resolve( DependencyResolverRequest request ); /** - * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. If - * the coordinate needs to be resolved too, use - * {@link #resolveDependencies(Session, List, List, Predicate< Node >)} passing - * {@code Collections.singletonList(coordinate)} + * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. * * @param session The {@link Session}, must not be {@code null}. * @param root {@link Dependency} @@ -58,31 +56,30 @@ DependencyResolverResult resolve( DependencyResolverRequest request ) * when downloading (can be {@code null}). * @return the resolved dependencies. * @throws DependencyResolverException in case of an error. + * @throws IllegalArgumentException if {@code request} is null or invalid */ - default DependencyResolverResult resolve( Session session, - Dependency root, - Predicate filter ) - throws DependencyResolverException + @Nonnull + default DependencyResolverResult resolve( @Nonnull Session session, + @Nonnull Dependency root, + @Nullable Predicate filter ) { return resolve( DependencyResolverRequest.build( session, root, filter ) ); } /** - * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. If - * the coordinate needs to be resolved too, use - * {@link #resolveDependencies(Session, List, List, Predicate< Node >)} passing - * {@code Collections.singletonList(coordinate)} + * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. * * @param session The {@link Session}, must not be {@code null}. * @param project {@link Project} - * @param filter {@link Predicate< Node >} (can be {@code null}). + * @param filter {@link Predicate} (can be {@code null}). * @return the resolved dependencies. * @throws DependencyResolverException in case of an error. + * @throws IllegalArgumentException if {@code session} or {@code project} is null or invalid */ - default DependencyResolverResult resolve( Session session, - Project project, - Predicate filter ) - throws DependencyResolverException + @Nonnull + default DependencyResolverResult resolve( @Nonnull Session session, + @Nonnull Project project, + @Nullable Predicate filter ) { return resolve( DependencyResolverRequest.build( session, project, filter ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java index e20e857b733b..ed01ba6b5578 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java @@ -19,7 +19,9 @@ * under the License. */ +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; import org.apache.maven.api.annotations.Nullable; import java.util.ArrayList; @@ -35,9 +37,12 @@ import org.apache.maven.api.Node; import org.apache.maven.api.Project; +import static org.apache.maven.api.services.BaseRequest.nonNull; + /** * A request to collect and resolve a dependency graph. */ +@Immutable public interface DependencyResolverRequest extends DependencyCollectorRequest { @@ -57,8 +62,8 @@ static DependencyResolverRequest build( @Nonnull Session session, @Nullable Predicate filter ) { return builder() - .session( session ) - .rootArtifact( root ) + .session( nonNull( session, "session can not be null" ) ) + .rootArtifact( nonNull( root, "root can not be null" ) ) .filter( filter ) .build(); } @@ -76,8 +81,8 @@ static DependencyResolverRequest build( @Nonnull Session session, @Nullable Predicate filter ) { return builder() - .session( session ) - .root( root ) + .session( nonNull( session, "session can not be null" ) ) + .root( nonNull( root, "root can not be null" ) ) .filter( filter ) .build(); } @@ -94,7 +99,8 @@ static DependencyResolverRequest build( @Nonnull Session session, @Nonnull Project project, @Nullable Predicate filter ) { - BaseRequest.requireNonNull( session, "session" ); + nonNull( session, "session can not be null" ); + nonNull( project, "project can not be null" ); return builder() .session( session ) .root( session.createDependency( project.getArtifact() ) ) @@ -110,6 +116,7 @@ static DependencyResolverRequestBuilder builder() return new DependencyResolverRequestBuilder(); } + @NotThreadSafe class DependencyResolverRequestBuilder { Session session; @@ -147,7 +154,7 @@ public DependencyResolverRequestBuilder rootArtifact( Artifact rootArtifact ) /** * * @param root The root dependency - * @return + * @return This request for chaining, never {@code null}. */ @Nonnull public DependencyResolverRequestBuilder root( @Nonnull Dependency root ) @@ -178,7 +185,7 @@ public DependencyResolverRequestBuilder dependencies( List dependenc * @return This request for chaining, never {@code null}. */ @Nonnull - public DependencyResolverRequestBuilder dependency( Dependency dependency ) + public DependencyResolverRequestBuilder dependency( @Nullable Dependency dependency ) { if ( dependency != null ) { @@ -214,7 +221,7 @@ public DependencyResolverRequestBuilder managedDependencies( List ma * @return This request for chaining, never {@code null}. */ @Nonnull - public DependencyResolverRequestBuilder managedDependency( Dependency managedDependency ) + public DependencyResolverRequestBuilder managedDependency( @Nullable Dependency managedDependency ) { if ( managedDependency != null ) { @@ -228,7 +235,7 @@ public DependencyResolverRequestBuilder managedDependency( Dependency managedDep } @Nonnull - public DependencyResolverRequestBuilder filter( Predicate filter ) + public DependencyResolverRequestBuilder filter( @Nullable Predicate filter ) { this.filter = filter; return this; @@ -274,10 +281,8 @@ private static class DefaultDependencyResolverRequest extends BaseRequest super( session ); this.rootArtifact = rootArtifact; this.root = root; - this.dependencies = dependencies != null && !dependencies.isEmpty() - ? unmodifiable( dependencies, "dependencies" ) : Collections.emptyList(); - this.managedDependencies = managedDependencies != null && !managedDependencies.isEmpty() - ? unmodifiable( managedDependencies, "managedDependencies" ) : Collections.emptyList(); + this.dependencies = unmodifiable( dependencies ); + this.managedDependencies = unmodifiable( managedDependencies ); this.filter = filter; } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java index 78d10b0c3a3b..bf857576e45c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -29,27 +29,58 @@ public interface ProjectBuilder extends Service { + /** + * Creates a {@link org.apache.maven.api.Project} from a POM file. + * + * @param request {@link ProjectBuilderRequest} + * @return the {@link ProjectBuilderResult} containing the built project and possible errors + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + */ @Nonnull - ProjectBuilderResult build( ProjectBuilderRequest request ) - throws ProjectBuilderException, IllegalArgumentException; + ProjectBuilderResult build( ProjectBuilderRequest request ); + /** + * Creates a {@link org.apache.maven.api.Project} from a POM file. + * + * @param session The {@link Session}, must not be {@code null}. + * @param source The {@link ProjectBuilderSource}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ @Nonnull default ProjectBuilderResult build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) - throws ProjectBuilderException, IllegalArgumentException { return build( ProjectBuilderRequest.build( session, source ) ); } + /** + * Creates a {@link org.apache.maven.api.Project} from a POM file. + * + * @param session The {@link Session}, must not be {@code null}. + * @param path The {@link Path}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ @Nonnull default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Path path ) - throws ProjectBuilderException, IllegalArgumentException { return build( ProjectBuilderRequest.build( session, path ) ); } + /** + * Creates a {@link org.apache.maven.api.Project} from an artifact. + * + * @param session The {@link Session}, must not be {@code null}. + * @param artifact The {@link Artifact}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ @Nonnull default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Artifact artifact ) - throws ProjectBuilderException, IllegalArgumentException { return build( ProjectBuilderRequest.build( session, artifact ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java index e5f72997be85..f4b1d7db7f90 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -19,7 +19,9 @@ * under the License. */ +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; import org.apache.maven.api.annotations.Nullable; import java.nio.file.Path; @@ -28,6 +30,9 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +import static org.apache.maven.api.services.BaseRequest.nonNull; + +@Immutable public interface ProjectBuilderRequest { @@ -55,8 +60,8 @@ public interface ProjectBuilderRequest static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull ProjectBuilderSource source ) { return builder() - .session( session ) - .source( source ) + .session( nonNull( session, "session can not be null" ) ) + .source( nonNull( source, "source can not be null" ) ) .build(); } @@ -64,8 +69,8 @@ static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull ProjectBu static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Path path ) { return builder() - .session( session ) - .path( path ) + .session( nonNull( session, "session can not be null" ) ) + .path( nonNull( path, "path can not be null" ) ) .build(); } @@ -73,8 +78,8 @@ static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Path path static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Artifact artifact ) { return builder() - .session( session ) - .artifact( artifact ) + .session( nonNull( session, "session can not be null" ) ) + .artifact( nonNull( artifact, "artifact can not be null" ) ) .build(); } @@ -84,6 +89,7 @@ static ProjectBuilderRequestBuilder builder() return new ProjectBuilderRequestBuilder(); } + @NotThreadSafe class ProjectBuilderRequestBuilder { Session session; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java index b430ad20032b..eaea90b7eab8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java @@ -23,15 +23,19 @@ import org.apache.maven.api.LocalRepository; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Repository; public interface RepositoryFactory extends Service { - LocalRepository createLocal( Path path ); + @Nonnull + LocalRepository createLocal( @Nonnull Path path ); - RemoteRepository createRemote( String id, String url ); + @Nonnull + RemoteRepository createRemote( @Nonnull String id, @Nonnull String url ); - RemoteRepository createRemote( Repository repository ); + @Nonnull + RemoteRepository createRemote( @Nonnull Repository repository ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java index e953f1db60fd..3ff928c0b52d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java @@ -22,6 +22,7 @@ /** * Resolution scope * TODO: merge this with {@link org.apache.maven.api.plugin.annotations.ResolutionScope} + * TODO: should this simply be an EnumSet instead ? */ public enum ResolutionScope { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java index 2740477689b2..7c5da04d97fb 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java @@ -27,15 +27,43 @@ public interface ToolchainManager extends Service { - List getToolchains( Session session, String type, Map requirements ) - throws ToolchainManagerException; + /** + * + * @param session + * @param type + * @param requirements + * @return the selected {@link Toolchain}s + * @throws ToolchainManagerException if an exceptino occurs + */ + List getToolchains( Session session, String type, Map requirements ); + + /** + * + * @param session + * @param type + * @return the selected {@link Toolchain} + * @throws ToolchainManagerException if an exceptino occurs + */ Toolchain getToolchainFromBuildContext( Session session, String type ) throws ToolchainManagerException; + /** + * + * @param session + * @param type + * @return the selected {@link Toolchain}s + * @throws ToolchainManagerException if an exceptino occurs + */ List getToolchainsForType( Session session, String type ) throws ToolchainManagerException; + /** + * + * @param session + * @param toolchain + * @throws ToolchainManagerException if an exceptino occurs + */ void storeToolchainToBuildContext( Session session, Toolchain toolchain ) throws ToolchainManagerException; } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java index 31a30681e263..4bb71c238ace 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java @@ -24,6 +24,11 @@ import java.net.URL; import java.nio.file.Path; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; + +@Immutable public interface XmlReaderRequest { @@ -58,11 +63,13 @@ interface Transformer String transform( String source, String fieldName ); } + @Nonnull static XmlReaderRequestBuilder builder() { return new XmlReaderRequestBuilder(); } + @NotThreadSafe class XmlReaderRequestBuilder { Path path; diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java index 865f8d09c3a0..af125a2492bf 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java @@ -25,6 +25,7 @@ @Documented @Retention( RetentionPolicy.CLASS ) +@ThreadSafe public @interface Immutable { } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java similarity index 67% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java rename to api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java index 2a1cf373dc99..a69fab6abd16 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryException.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java @@ -1,4 +1,4 @@ -package org.apache.maven.api.services; +package org.apache.maven.api.annotations; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -9,7 +9,7 @@ * "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 + * 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 @@ -19,18 +19,12 @@ * under the License. */ -public class ArtifactFactoryException - extends MavenException -{ - - public ArtifactFactoryException( String message ) - { - super( message ); - } - - public ArtifactFactoryException( String message, Throwable cause ) - { - super( message, cause ); - } +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface NotThreadSafe +{ } diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 97227ab26ced..1034a0962c05 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -49,7 +49,10 @@ #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) #foreach ( $field in $allFields ) #if ( $field.type == "java.util.List" ) #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) @@ -88,7 +91,7 @@ package ${package}; import $imp; #end -@Generated +@Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) extends ${class.superClass} @@ -230,6 +233,7 @@ public class ${class.name} #end } + @Nonnull public Builder with() { return newBuilder( this ); @@ -237,42 +241,50 @@ public class ${class.name} #foreach ( $field in $allFields ) #set ( $cap = $Helper.capitalise( $field.name ) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + @Nonnull public ${class.name} with${cap}( $type $field.name ) { return with().${field.name}( $field.name ).build(); } #end + @Nonnull public static ${class.name} newInstance() { return newInstance( true ); } + @Nonnull public static ${class.name} newInstance( boolean withDefaults ) { return newBuilder( withDefaults ).build(); } + @Nonnull public static Builder newBuilder() { return newBuilder( true ); } + @Nonnull public static Builder newBuilder( boolean withDefaults ) { return new Builder( withDefaults ); } + @Nonnull public static Builder newBuilder( ${class.name} from ) { return newBuilder( from, false ); } + @Nonnull public static Builder newBuilder( ${class.name} from, boolean forceCopy ) { return new Builder( from, forceCopy ); } + @NotThreadSafe public static class Builder #if ( $class.superClass ) extends ${class.superClass}.Builder @@ -334,6 +346,7 @@ public class ${class.name} } #if ( $class == $root ) + @Nonnull public Builder modelEncoding( String modelEncoding ) { this.modelEncoding = modelEncoding; @@ -342,6 +355,7 @@ public class ${class.name} #end #foreach ( $field in $allFields ) + @Nonnull public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) { this.${field.name} = ${field.name}; @@ -350,6 +364,7 @@ public class ${class.name} #end + @Nonnull public Builder location( Object key, InputLocation location ) { if ( this.locations == null ) @@ -360,6 +375,7 @@ public class ${class.name} return this; } + @Nonnull public ${class.name} build() { if ( base != null diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java index 5ff2ff4194a7..7d18c94be39a 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -28,15 +28,20 @@ import org.apache.maven.api.Artifact; +import static org.apache.maven.internal.impl.Utils.nonNull; + +/** + * A wrapper class around a maven resolver artifact. + */ public class DefaultArtifact implements Artifact { - private final DefaultSession session; - private final org.eclipse.aether.artifact.Artifact artifact; + private final @Nonnull DefaultSession session; + private final @Nonnull org.eclipse.aether.artifact.Artifact artifact; public DefaultArtifact( @Nonnull DefaultSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact ) { - this.session = Objects.requireNonNull( session ); - this.artifact = Objects.requireNonNull( artifact ); + this.session = nonNull( session, "session can not be null" ); + this.artifact = nonNull( artifact, "artifact can not be null" ); } public org.eclipse.aether.artifact.Artifact getArtifact() diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java index 39df5f1769bf..f6be945bf2b2 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactDeployer.java @@ -19,13 +19,14 @@ * under the License. */ +import org.apache.maven.api.Artifact; +import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.annotations.Nonnull; import javax.inject.Inject; import javax.inject.Named; import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.stream.Collectors; import org.apache.maven.api.services.ArtifactDeployer; @@ -38,32 +39,42 @@ import org.eclipse.aether.deployment.DeploymentException; import org.eclipse.aether.metadata.Metadata; +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +/** + * Implementation of {@link ArtifactDeployer} service. + */ @Named public class DefaultArtifactDeployer implements ArtifactDeployer { - private final RepositorySystem repositorySystem; + private final @Nonnull RepositorySystem repositorySystem; @Inject DefaultArtifactDeployer( @Nonnull RepositorySystem repositorySystem ) { - this.repositorySystem = Objects.requireNonNull( repositorySystem ); + this.repositorySystem = nonNull( repositorySystem, "repositorySystem can not be null" ); } @Override - public void deploy( ArtifactDeployerRequest request ) throws ArtifactDeployerException, IllegalArgumentException + public void deploy( @Nonnull ArtifactDeployerRequest request ) { - DefaultSession session = ( DefaultSession ) request.getSession(); + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + Collection artifacts = nonNull( request.getArtifacts(), "request.artifacts can not be null" ); + RemoteRepository repository = nonNull( request.getRepository(), "request.repository can not be null" ); try { ArtifactManager artifactManager = session.getService( ArtifactManager.class ); - List metadatas = request.getArtifacts().stream() + List metadatas = artifacts.stream() .map( artifactManager::getAttachedMetadatas ) .flatMap( Collection::stream ) .map( session::toMetadata ) .collect( Collectors.toList() ); DeployRequest deployRequest = new DeployRequest() - .setRepository( session.toRepository( request.getRepository() ) ) - .setArtifacts( session.toArtifacts( request.getArtifacts() ) ) + .setRepository( session.toRepository( repository ) ) + .setArtifacts( session.toArtifacts( artifacts ) ) .setMetadata( metadatas ); DeployResult result = repositorySystem.deploy( session.getSession(), deployRequest ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java index e4f9b94bc72f..c5dd9a1c2104 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactFactory.java @@ -21,22 +21,25 @@ import javax.inject.Named; -import java.security.InvalidParameterException; - import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.services.ArtifactFactory; -import org.apache.maven.api.services.ArtifactFactoryException; import org.apache.maven.api.services.ArtifactFactoryRequest; import org.apache.maven.shared.utils.StringUtils; import org.eclipse.aether.artifact.ArtifactType; +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + @Named public class DefaultArtifactFactory implements ArtifactFactory { @Override - public Artifact create( ArtifactFactoryRequest request ) throws ArtifactFactoryException, InvalidParameterException + public Artifact create( @Nonnull ArtifactFactoryRequest request ) { - DefaultSession session = (DefaultSession) request.getSession(); + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); ArtifactType type = null; if ( request.getType() != null ) { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java index 06a0cc4b4afd..dba2fa80a469 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactInstaller.java @@ -23,7 +23,6 @@ import java.util.Collection; import java.util.List; -import java.util.Objects; import java.util.stream.Collectors; import org.apache.maven.api.services.ArtifactInstaller; @@ -36,6 +35,9 @@ import org.eclipse.aether.installation.InstallationException; import org.eclipse.aether.metadata.Metadata; +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + public class DefaultArtifactInstaller implements ArtifactInstaller { @@ -43,48 +45,15 @@ public class DefaultArtifactInstaller implements ArtifactInstaller DefaultArtifactInstaller( @Nonnull RepositorySystem repositorySystem ) { - this.repositorySystem = Objects.requireNonNull( repositorySystem ); + this.repositorySystem = nonNull( repositorySystem ); } @Override public void install( ArtifactInstallerRequest request ) throws ArtifactInstallerException, IllegalArgumentException { - - /* - // prepare installRequest - InstallRequest request = new InstallRequest(); - - // transform artifacts - for ( org.apache.maven.artifact.Artifact mavenArtifact : mavenArtifacts ) - { - Artifact mainArtifact = RepositoryUtils.toArtifact( mavenArtifact ); - request.addArtifact( mainArtifact ); - - for ( ArtifactMetadata metadata : mavenArtifact.getMetadataList() ) - { - if ( metadata instanceof ProjectArtifactMetadata ) - { - Artifact pomArtifact = new SubArtifact( mainArtifact, "", "pom" ); - pomArtifact = pomArtifact.setFile( ( (ProjectArtifactMetadata) metadata ).getFile() ); - request.addArtifact( pomArtifact ); - } - else if ( // metadata instanceof SnapshotArtifactRepositoryMetadata || - metadata instanceof ArtifactRepositoryMetadata ) - { - // eaten, handled by repo system - } - else if ( metadata instanceof org.apache.maven.shared.transfer.metadata.ArtifactMetadata ) - { - org.apache.maven.shared.transfer.metadata.ArtifactMetadata transferMetadata = - (org.apache.maven.shared.transfer.metadata.ArtifactMetadata) metadata; - - request.addMetadata( new Maven31MetadataBridge( metadata ).setFile( transferMetadata.getFile() ) ); - } - } - } - */ - - DefaultSession session = ( DefaultSession ) request.getSession(); + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); try { ArtifactManager artifactManager = session.getService( ArtifactManager.class ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java index bc5b58b3dc19..551a99260673 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java @@ -22,8 +22,6 @@ import org.apache.maven.api.annotations.Nonnull; import javax.inject.Inject; -import java.util.Objects; - import org.apache.maven.api.Artifact; import org.apache.maven.api.services.ArtifactResolver; import org.apache.maven.api.services.ArtifactResolverException; @@ -34,6 +32,9 @@ import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.ArtifactResult; +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + public class DefaultArtifactResolver implements ArtifactResolver { private final RepositorySystem repositorySystem; @@ -41,14 +42,16 @@ public class DefaultArtifactResolver implements ArtifactResolver @Inject DefaultArtifactResolver( @Nonnull RepositorySystem repositorySystem ) { - this.repositorySystem = Objects.requireNonNull( repositorySystem ); + this.repositorySystem = nonNull( repositorySystem, "repositorySystem can not be null" ); } @Override public ArtifactResolverResult resolve( ArtifactResolverRequest request ) throws ArtifactResolverException, IllegalArgumentException { - DefaultSession session = ( DefaultSession ) request.getSession(); + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); try { ArtifactRequest req = new ArtifactRequest() diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java index c3dccd60fc8c..d308088caf1d 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java @@ -23,12 +23,13 @@ import org.apache.maven.api.annotations.Nullable; import java.util.Collection; -import java.util.Objects; import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; import org.apache.maven.api.Exclusion; +import static org.apache.maven.internal.impl.Utils.nonNull; + public class DefaultDependency implements Dependency { private final DefaultSession session; @@ -36,8 +37,8 @@ public class DefaultDependency implements Dependency public DefaultDependency( @Nonnull DefaultSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency ) { - this.session = Objects.requireNonNull( session, "session" ); - this.dependency = Objects.requireNonNull( dependency, "dependency" ); + this.session = nonNull( session, "session" ); + this.dependency = nonNull( dependency, "dependency" ); } @Nonnull diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java index 1a5efb2ccb5a..7edd4f7a53ee 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java @@ -37,6 +37,9 @@ import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.graph.Dependency; +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + @Named public class DefaultDependencyCollector implements DependencyCollector { @@ -54,7 +57,9 @@ public class DefaultDependencyCollector implements DependencyCollector public DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest request ) throws DependencyCollectorException, IllegalArgumentException { - DefaultSession session = ( DefaultSession ) request.getSession(); + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); Artifact rootArtifact = request.getRootArtifact().map( session::toArtifact ).orElse( null ); Dependency root = request.getRoot().map( session::toDependency ).orElse( null ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java index aa83ffb7a76d..62327ed70634 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java @@ -25,19 +25,25 @@ import org.apache.maven.api.Dependency; import org.apache.maven.api.Exclusion; +import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.services.DependencyFactory; -import org.apache.maven.api.services.DependencyFactoryException; import org.apache.maven.api.services.DependencyFactoryRequest; +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + @Named public class DefaultDependencyFactory implements DependencyFactory { + @Nonnull @Override - public Dependency create( DependencyFactoryRequest request ) - throws DependencyFactoryException, IllegalArgumentException + public Dependency create( @Nonnull DependencyFactoryRequest request ) { - DefaultSession session = ( DefaultSession ) request.getSession(); + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + return new DefaultDependency( session, new org.eclipse.aether.graph.Dependency( diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java index 9372576a8afa..618333e1c824 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLocalRepository.java @@ -23,21 +23,23 @@ import javax.inject.Inject; import java.nio.file.Path; -import java.util.Objects; import org.apache.maven.api.LocalRepository; +import static org.apache.maven.internal.impl.Utils.nonNull; + public class DefaultLocalRepository implements LocalRepository { - private final org.eclipse.aether.repository.LocalRepository repository; + private final @Nonnull org.eclipse.aether.repository.LocalRepository repository; @Inject public DefaultLocalRepository( @Nonnull org.eclipse.aether.repository.LocalRepository repository ) { - this.repository = Objects.requireNonNull( repository, "repository" ); + this.repository = nonNull( repository, "repository can not be null" ); } + @Nonnull public org.eclipse.aether.repository.LocalRepository getRepository() { return repository; diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java index 68e276f3f7ad..55a6f8796445 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java @@ -25,7 +25,6 @@ import java.io.Writer; import java.net.URL; import java.nio.file.Path; -import java.util.Objects; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.services.xml.ModelXmlFactory; @@ -39,13 +38,15 @@ import org.apache.maven.model.v4.MavenXpp3WriterEx; import org.codehaus.plexus.util.ReaderFactory; +import static org.apache.maven.internal.impl.Utils.nonNull; + public class DefaultModelXmlFactory implements ModelXmlFactory { @Override public Model read( @Nonnull XmlReaderRequest request ) throws XmlReaderException { - Objects.requireNonNull( request, "request can not be null" ); + nonNull( request, "request can not be null" ); Path path = request.getPath(); URL url = request.getURL(); Reader reader = request.getReader(); @@ -86,8 +87,8 @@ else if ( inputStream != null ) @Override public void write( XmlWriterRequest request ) throws XmlWriterException { - Objects.requireNonNull( request, "request can not be null" ); - Model content = Objects.requireNonNull( request.getContent(), "content can not be null" ); + nonNull( request, "request can not be null" ); + Model content = nonNull( request.getContent(), "content can not be null" ); OutputStream outputStream = request.getOutputStream(); Writer writer = request.getWriter(); if ( writer == null && outputStream == null ) diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java index 375758c87847..a11611f1e9d7 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java @@ -29,15 +29,16 @@ import org.apache.maven.api.NodeVisitor; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Repository; +import org.apache.maven.api.annotations.Nonnull; public class DefaultNode implements Node { - private final DefaultSession session; - private final org.eclipse.aether.graph.DependencyNode node; + private final @Nonnull DefaultSession session; + private final @Nonnull org.eclipse.aether.graph.DependencyNode node; - public DefaultNode( DefaultSession session, - org.eclipse.aether.graph.DependencyNode node ) + public DefaultNode( @Nonnull DefaultSession session, + @Nonnull org.eclipse.aether.graph.DependencyNode node ) { this.session = session; this.node = node; diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java index 365ad3d1ed32..17fa50990276 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -27,6 +27,8 @@ import java.util.Collection; import java.util.Collections; import java.util.List; +import java.util.Locale; +import java.util.Optional; import org.apache.maven.RepositoryUtils; import org.apache.maven.api.Artifact; @@ -103,10 +105,10 @@ public Model getModel() @Nonnull @Override - public Path getPomPath() + public Optional getPomPath() { File file = project.getFile(); - return file != null ? file.toPath() : null; + return Optional.ofNullable( file ).map( File::toPath ); } @Nonnull @@ -134,6 +136,7 @@ public boolean isExecutionRoot() return project.isExecutionRoot(); } + @Nonnull private Dependency toDependency( org.apache.maven.api.model.Dependency dependency ) { return new Dependency() @@ -150,7 +153,7 @@ public Artifact getArtifact() @Override public String getScope() { - return dependency.getScope(); + return dependency.getScope().toUpperCase( Locale.ROOT ); } @Override diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index db00e4e5600b..dea547948724 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -74,6 +74,8 @@ import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; +import static org.apache.maven.internal.impl.Utils.nonNull; + public class DefaultSession implements Session { @@ -106,9 +108,9 @@ public DefaultSession( @Nonnull MavenSession session, @Nonnull MavenRepositorySystem mavenRepositorySystem, @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate ) { - this.mavenSession = Objects.requireNonNull( session ); + this.mavenSession = nonNull( session ); this.session = mavenSession.getRepositorySession(); - this.repositorySystem = Objects.requireNonNull( repositorySystem ); + this.repositorySystem = nonNull( repositorySystem ); this.repositories = repositories != null ? repositories : mavenSession.getRequest().getRemoteRepositories().stream() @@ -203,7 +205,7 @@ public Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier su @Override public Session withLocalRepository( @Nonnull LocalRepository localRepository ) { - Objects.requireNonNull( localRepository, "localRepository" ); + nonNull( localRepository, "localRepository" ); if ( session.getLocalRepository() != null && Objects.equals( session.getLocalRepository().getBasedir().toPath(), localRepository.getPath() ) ) @@ -302,11 +304,13 @@ else if ( clazz == ToolchainsXmlFactory.class ) throw new NoSuchElementException( clazz.getName() ); } + @Nonnull public RepositorySystemSession getSession() { return session; } + @Nonnull public RepositorySystem getRepositorySystem() { return repositorySystem; @@ -322,12 +326,14 @@ public Node getNode( org.eclipse.aether.graph.DependencyNode node ) return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n ) ); } - public Artifact getArtifact( org.eclipse.aether.artifact.Artifact artifact ) + @Nonnull + public Artifact getArtifact( @Nonnull org.eclipse.aether.artifact.Artifact artifact ) { return allArtifacts.computeIfAbsent( artifact, a -> new DefaultArtifact( this, a ) ); } - public Dependency getDependency( org.eclipse.aether.graph.Dependency dependency ) + @Nonnull + public Dependency getDependency( @Nonnull org.eclipse.aether.graph.Dependency dependency ) { return allDependencies.computeIfAbsent( dependency, d -> new DefaultDependency( this, d ) ); } @@ -506,13 +512,13 @@ else if ( metadata instanceof org.apache.maven.shared.transfer.metadata.Artifact @Override public void registerListener( @Nonnull Listener listener ) { - listeners.add( listener ); + listeners.add( nonNull( listener ) ); } @Override public void unregisterListener( @Nonnull Listener listener ) { - listeners.remove( listener ); + listeners.remove( nonNull( listener ) ); } @Nonnull diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java b/maven-core/src/main/java/org/apache/maven/internal/impl/Utils.java similarity index 55% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java rename to maven-core/src/main/java/org/apache/maven/internal/impl/Utils.java index e0c5f2fa8624..675f397017ba 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryException.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/Utils.java @@ -1,4 +1,4 @@ -package org.apache.maven.api.services; +package org.apache.maven.internal.impl; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -9,7 +9,7 @@ * "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 + * 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 @@ -19,18 +19,33 @@ * under the License. */ -public class DependencyFactoryException - extends MavenException +class Utils { + static T nonNull( T t ) + { + if ( t == null ) + { + throw new IllegalArgumentException(); + } + return t; + } - public DependencyFactoryException( String message ) + static T nonNull( T t, String message ) { - super( message ); + if ( t == null ) + { + throw new IllegalArgumentException( message ); + } + return t; } - public DependencyFactoryException( String message, Throwable cause ) + static T cast( Class clazz, Object o, String message ) { - super( message, cause ); + if ( ! clazz.isInstance( o ) ) + { + throw new IllegalArgumentException( message ); + } + return clazz.cast( o ); } } From ab2845f166e7fde63a1e18020304f582cb960e9b Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 5 Apr 2022 09:23:19 +0200 Subject: [PATCH 15/98] More fixes --- .../providers/AbstractLifecycleProvider.java | 3 +- .../model/building/DefaultModelBuilder.java | 10 +++++- .../plugin/DefaultReportingConverter.java | 34 +++++++++++++------ 3 files changed, 35 insertions(+), 12 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java index e167cac59b9b..27ea758c7d3a 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/AbstractLifecycleProvider.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashMap; +import java.util.LinkedHashMap; import javax.inject.Provider; @@ -48,7 +49,7 @@ protected AbstractLifecycleProvider( String id, String[] phases, String[] plugin throw new IllegalArgumentException( "Plugin bindings must have more than 0, even count of elements" ); } - defaultBindings = new HashMap<>( len / 2 ); + defaultBindings = new LinkedHashMap<>( len / 2 ); for ( int i = 0; i < len; i += 2 ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 22055d351fa3..87f2bfef3a9d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1080,7 +1080,15 @@ private void configureResolver( ModelResolver modelResolver, Model model, Defaul { try { - modelResolver.addRepository( repository, replaceRepositories ); + try + { + modelResolver.addRepository( repository, replaceRepositories ); + } + catch ( AbstractMethodError e ) + { + modelResolver.addRepository( new org.apache.maven.model.Repository( repository ), + replaceRepositories ); + } } catch ( InvalidRepositoryException e ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java index 3f109f6b90c7..fa6b64f1cba8 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java @@ -160,22 +160,36 @@ public Model convertReporting( Model model, ModelBuildingRequest request, ModelP configChildren.add( newDom( "reportPlugins", reportPlugins, location ) ); configuration = newDom( "configuration", configChildren, location ); - sitePlugin = sitePlugin.withConfiguration( configuration ); + Plugin finalSitePlugin = sitePlugin.withConfiguration( configuration ); - PluginManagement pluginManagement = build.getPluginManagement(); - if ( pluginManagement == null ) + Plugin sitePluginFromPlugins = build.getPlugins().stream() + .filter( this::isSitePlugin ).findFirst().orElse( null ); + if ( sitePluginFromPlugins != null ) { - pluginManagement = PluginManagement.newBuilder() - .plugins( Collections.singletonList( sitePlugin ) ) - .build(); + List plugins = new ArrayList<>( build.getPlugins() ); + plugins.replaceAll( p -> p == sitePluginFromPlugins ? finalSitePlugin : p ); + build = build.withPlugins( plugins ); + } + else if ( build.getPluginManagement() == null ) + { + build = build.withPluginManagement( PluginManagement.newBuilder() + .plugins( Collections.singletonList( finalSitePlugin ) ).build() ); } else { - List plugins = new ArrayList<>( pluginManagement.getPlugins() ); - plugins.add( sitePlugin ); - pluginManagement = pluginManagement.withPlugins( plugins ); + Plugin sitePluginFromManagement = build.getPluginManagement().getPlugins().stream() + .filter( this::isSitePlugin ).findFirst().orElse( null ); + List plugins = new ArrayList<>( build.getPluginManagement().getPlugins() ); + if ( sitePluginFromManagement != null ) + { + plugins.replaceAll( p -> p == sitePluginFromManagement ? finalSitePlugin : p ); + } + else + { + plugins.add( finalSitePlugin ); + } + build = build.withPluginManagement( build.getPluginManagement().withPlugins( plugins ) ); } - build = build.withPluginManagement( pluginManagement ); return builder.build( build ).build(); } From a834c445770fbd592f9ef0887aa116212bac03a2 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 5 Apr 2022 11:03:20 +0200 Subject: [PATCH 16/98] Import Dom type and relax List to Collection in the builders --- api/maven-api-model/src/main/mdo/model.vm | 15 +++++++++++++-- 1 file changed, 13 insertions(+), 2 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 1034a0962c05..43752fc65699 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -42,7 +42,7 @@ #set ( $root = $class ) #end #end - #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) #set ( $dummy = $imports.add( "java.util.Collections" ) ) @@ -56,8 +56,12 @@ #foreach ( $field in $allFields ) #if ( $field.type == "java.util.List" ) #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) #set ( $dummy = $imports.add( "java.util.List" ) ) #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) #else #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) #set ( $idx = $fieldType.lastIndexOf('.') ) @@ -296,6 +300,9 @@ public class ${class.name} #end #foreach ( $field in $class.allFields ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end #if ( $type == 'boolean' ) Boolean ${field.name}; #elseif ( $type == 'int' ) @@ -355,8 +362,12 @@ public class ${class.name} #end #foreach ( $field in $allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end @Nonnull - public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + public Builder ${field.name}( ${type} ${field.name} ) { this.${field.name} = ${field.name}; return this; From 57781f8051e3925eb6d339d2079b4aa788569d72 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 5 Apr 2022 16:26:36 +0200 Subject: [PATCH 17/98] USe {@code xx} instead of in javadoc --- api/maven-api-model/src/main/mdo/maven.mdo | 276 ++++++++++----------- 1 file changed, 138 insertions(+), 138 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index 089ba8432153..4d69c741f706 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -71,7 +71,7 @@ ModelBase <project> element is the root of the descriptor. + The {@code } element is the root of the descriptor. The following table lists all of the possible child elements. ]]> @@ -125,7 +125,7 @@ org.apache.maven). + projects with a similar name (eg. {@code org.apache.maven}). ]]> String @@ -152,10 +152,10 @@ 4.0.0+ jar - war - ear - pom. + The type of artifact this project produces, for example {@code jar} + {@code war} + {@code ear} + {@code pom}. Plugins can create their own packaging, and therefore their own packaging types, so this list does not contain all possible types. @@ -193,7 +193,7 @@ Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - project's child.project.url.inherit.append.path="false" + project's {@code child.project.url.inherit.append.path="false"} ]]> String @@ -204,9 +204,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -237,7 +237,7 @@ license element, which + Each license is described by a {@code license} element, which is then described by additional elements. Projects should only list the license(s) that applies to the project and not the licenses that apply to dependencies. @@ -392,7 +392,7 @@ } /** - * @return the model id as groupId:artifactId:packaging:version + * @return the model id as {@code groupId:artifactId:packaging:version} */ public String getId() { @@ -444,7 +444,7 @@ } /** - * @return the model id as groupId:artifactId:packaging:version + * @return the model id as {@code groupId:artifactId:packaging:version} */ public String getId() { @@ -482,7 +482,7 @@ 3.0.0+ Model and the Profile objects. + Base class for the {@code Model} and the {@code Profile} objects. ]]> @@ -514,7 +514,7 @@ <name>value</name>. + The format is {@code value}. ]]> Properties @@ -582,7 +582,7 @@ mvn site. + These reports will be run when a user executes {@code mvn site}. All of the reports will be included in the navigation bar for browsing. ]]> @@ -615,7 +615,7 @@ Map pluginMap; /** - * Reset the pluginsMap field to null + * Reset the {@code pluginsMap} field to {@code null} */ public synchronized void flushPluginMap() { @@ -623,7 +623,7 @@ } /** - * @return a Map of plugins field with Plugins#getKey() as key + * @return a Map of plugins field with {@code Plugins#getKey()} as key * @see org.apache.maven.model.Plugin#getKey() */ public synchronized Map getPluginsAsMap() @@ -692,7 +692,7 @@ This element describes all of the classpath resources such as properties files associated with a project. These resources are often included in the final package. - The default value is src/main/resources.]]> + The default value is {@code src/main/resources}.]]> Resource @@ -705,7 +705,7 @@ src/test/resources.]]> + The default value is {@code src/test/resources}.]]> Resource @@ -717,7 +717,7 @@ 4.0.0+ target.]]> + The default value is {@code target}.]]> String @@ -728,7 +728,7 @@ ${artifactId}-${version}. + The default value is {@code ${artifactId}-${version}}. ]]> String @@ -750,7 +750,7 @@ BuildBase <build> element contains informations required to build the project. + The {@code } element contains informations required to build the project. Default values are defined in Super POM. ]]> @@ -763,7 +763,7 @@ This element specifies a directory containing the source of the project. The generated build system will compile the sources from this directory when the project is built. The path given is relative to the project descriptor. - The default value is src/main/java.]]> + The default value is {@code src/main/java}.]]> String @@ -776,7 +776,7 @@ project. This directory is meant to be different from the sourceDirectory, in that its contents will be copied to the output directory in most cases (since scripts are interpreted rather than compiled). - The default value is src/main/scripts.]]> + The default value is {@code src/main/scripts}.]]> String @@ -788,7 +788,7 @@ This element specifies a directory containing the unit test source of the project. The generated build system will compile these directories when the project is being tested. The path given is relative to the project descriptor. - The default value is src/test/java.]]> + The default value is {@code src/test/java}.]]> String @@ -797,7 +797,7 @@ 4.0.0+ target/classes.]]> + The default value is {@code target/classes}.]]> String @@ -806,7 +806,7 @@ 4.0.0+ target/test-classes.]]> + The default value is {@code target/test-classes}.]]> String @@ -826,7 +826,7 @@ 4.0.0+ <CiManagement> element contains informations required to the + The {@code } element contains informations required to the continuous integration system of the project. ]]> @@ -836,7 +836,7 @@ 4.0.0+ continuum. + The name of the continuous integration system, e.g. {@code continuum}. ]]> String @@ -967,7 +967,7 @@ role element, the body of which is a role name. This can also be used to + {@code role} element, the body of which is a role name. This can also be used to describe the contribution. ]]> @@ -1005,7 +1005,7 @@ 3.0.0+ <dependency> element contains information about a dependency + The {@code } element contains information about a dependency of the project. ]]> @@ -1017,7 +1017,7 @@ org.apache.maven. + {@code org.apache.maven}. ]]> String @@ -1029,7 +1029,7 @@ maven-artifact. + {@code maven-artifact}. ]]> String @@ -1039,7 +1039,7 @@ 3.0.0+ 3.2.1. In Maven 2, this can also be + The version of the dependency, e.g. {@code 3.2.1}. In Maven 2, this can also be specified as a range of versions. ]]> @@ -1051,8 +1051,8 @@ jar, war, ejb-client - and test-jar: see default + Some examples are {@code jar}, {@code war}, {@code ejb-client} + and {@code test-jar}: see default artifact handlers for a list. New types can be defined by extensions, so this is not a complete list. ]]> @@ -1067,11 +1067,11 @@ The classifier of the dependency. It is appended to the filename after the version. This allows:
    -
  • referring to attached artifact, for example sources and javadoc: +
  • referring to attached artifact, for example {@code sources} and {@code javadoc}: see default artifact handlers for a list,
  • distinguishing two artifacts that belong to the same POM but were built differently. - For example, jdk14 and jdk15.
  • + For example, {@code jdk14} and {@code jdk15}.
]]> @@ -1083,13 +1083,13 @@ 4.0.0+ compile, runtime, - test, system, and provided. Used to + The scope of the dependency - {@code compile}, {@code runtime}, + {@code test}, {@code system}, and {@code provided}. Used to calculate the various classpaths used for compilation, testing, and so on. It also assists in determining which artifacts to include in a distribution of this project. For more information, see the - dependency mechanism. The default scope is compile. + dependency mechanism. The default scope is {@code compile}. ]]> String @@ -1109,7 +1109,7 @@ for this dependency. Requires an absolute path for the value, not relative. Use a property that gives the machine specific absolute path, - e.g. ${java.home}. + e.g. {@code ${java.home}}. ]]> String @@ -1132,8 +1132,8 @@ Indicates the dependency is optional for use of this library. While the version of the dependency will be taken into account for dependency calculation if the library is used elsewhere, it will not be passed on transitively. Note: While the type - of this field is String for technical reasons, the semantic type is actually - Boolean. Default value is false. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> String @@ -1166,7 +1166,7 @@ private volatile String managementKey; /** - * @return the management key as groupId:artifactId:type + * @return the management key as {@code groupId:artifactId:type} */ public String getManagementKey() { @@ -1200,7 +1200,7 @@ 4.0.0+ <exclusion> element contains informations required to exclude + The {@code } element contains informations required to exclude an artifact to the project. ]]> @@ -1262,7 +1262,7 @@ repository element. + {@code repository} element. ]]> @@ -1283,7 +1283,7 @@ url. + referred to the homepage given by {@code url}. This is given to assist in locating artifacts that are not in the repository due to licensing restrictions. ]]> @@ -1306,11 +1306,11 @@ none (default), - converted (repository manager converted this from an Maven 1 POM), - partner - (directly synced from a partner Maven 2 repository), deployed (was deployed from a Maven 2 - instance), verified (has been hand verified as correct and final). + tools placing it in the reposiory. Valid values are: {@code none} (default), + {@code converted} (repository manager converted this from an Maven 1 POM), + {@code partner} + (directly synced from a partner Maven 2 repository), {@code deployed} (was deployed from a Maven 2 + instance), {@code verified} (has been hand verified as correct and final). ]]> false @@ -1385,7 +1385,7 @@ mailto: link will automatically be created + {@code mailto:} link will automatically be created when the documentation is created. ]]> @@ -1398,7 +1398,7 @@ mailto: link will automatically be created + {@code mailto:} link will automatically be created when the documentation is created. ]]> @@ -1411,7 +1411,7 @@ mailto: link will automatically be created + {@code mailto:} link will automatically be created when the documentation is created. ]]> @@ -1466,7 +1466,7 @@ 3.0.0+ **/*.xml. + A list of patterns to include, e.g. {@code **/*.xml}. ]]> @@ -1479,7 +1479,7 @@ 3.0.0+ **/*.xml + A list of patterns to exclude, e.g. {@code **/*.xml} ]]> @@ -1529,7 +1529,7 @@ 4.0.0+ <parent> element contains information required to locate the parent project from which + The {@code } element contains information required to locate the parent project from which this project will inherit from. Note: The children of this element are not interpolated and must be given as literal values. ]]> @@ -1560,11 +1560,11 @@ 4.0.0+ pom.xml file within the check out. - If not specified, it defaults to ../pom.xml. + The relative path of the parent {@code pom.xml} file within the check out. + If not specified, it defaults to {@code ../pom.xml}. Maven looks for the parent POM first in this location on the filesystem, then the local repository, and lastly in the remote repo. - relativePath allows you to select a different location, + {@code relativePath} allows you to select a different location, for example when your structure is flat, or deeper without an intermediate parent POM. However, the group ID, artifact ID and version are still required, and must match the file in the location given or it will revert to the repository for the POM. @@ -1583,7 +1583,7 @@ groupId:artifactId:version + * @return the id as {@code groupId:artifactId:version} */ public String getId() { @@ -1616,7 +1616,7 @@ 4.0.0+ <scm> element contains informations required to the SCM + The {@code } element contains informations required to the SCM (Source Control Management) of the project. ]]> @@ -1633,7 +1633,7 @@ and list of supported SCMs. This connection is read-only.
Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - scm's child.scm.connection.inherit.append.path="false" + scm's {@code child.scm.connection.inherit.append.path="false"} ]]>
String @@ -1643,10 +1643,10 @@ 4.0.0+ connection, but for developers, i.e. this scm connection + Just like {@code connection}, but for developers, i.e. this scm connection will not be read only.
Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - scm's child.scm.developerConnection.inherit.append.path="false" + scm's {@code child.scm.developerConnection.inherit.append.path="false"} ]]>
String @@ -1665,7 +1665,7 @@ Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - scm's child.scm.url.inherit.append.path="false" + scm's {@code child.scm.url.inherit.append.path="false"} ]]>
String @@ -1676,9 +1676,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -1690,9 +1690,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -1704,9 +1704,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -1783,10 +1783,10 @@ ${project.build.outputDirectory}). + directory (i.e. {@code ${project.build.outputDirectory}}). For example, if you want that resource to appear in a specific package - (org.apache.maven.messages), you must specify this - element with this value: org/apache/maven/messages. + ({@code org.apache.maven.messages}), you must specify this + element with this value: {@code org/apache/maven/messages}. This is not required if you simply put the resources in that directory structure at the source, however. ]]> @@ -1799,10 +1799,10 @@ properties element and from the - properties in the files listed in the filters element. Note: While the type - of this field is String for technical reasons, the semantic type is actually - Boolean. Default value is false. + The values are taken from the {@code properties} element and from the + properties in the files listed in the {@code filters} element. Note: While the type + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> String @@ -1858,7 +1858,7 @@ settings.xml file, for example. Furthermore, the identifier is + to configuration in the {@code settings.xml} file, for example. Furthermore, the identifier is used during POM inheritance and profile injection to detect repositories that should be merged. ]]> @@ -1876,7 +1876,7 @@ true protocol://hostname/path. + The url of the repository, in the form {@code protocol://hostname/path}. ]]> String @@ -1887,7 +1887,7 @@ legacy or default. + can be {@code legacy} or {@code default}. ]]> String @@ -1951,8 +1951,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is true. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code true}. ]]> String @@ -1963,12 +1963,12 @@ always, - daily + {@code always,} + {@code daily} (default), - interval:XXX + {@code interval:XXX} (in minutes) or - never + {@code never} (only if it doesn't exist locally). ]]> @@ -1980,10 +1980,10 @@ ignore, - fail + {@code ignore}, + {@code fail} (default for Maven 4 and above) or - warn + {@code warn} (default for Maven 2 and 3) ]]> @@ -2019,7 +2019,7 @@ settings.xml file, for example. + site to configuration in the {@code settings.xml} file, for example. ]]> String @@ -2035,9 +2035,9 @@ 4.0.0+ protocol://hostname/path. + The url of the location where website is deployed, in the form {@code protocol://hostname/path}.
Default value is: parent value [+ path adjustment] + (artifactId or project.directory property), or just parent value if - site's child.site.url.inherit.append.path="false" + site's {@code child.site.url.inherit.append.path="false"} ]]>
String @@ -2048,9 +2048,9 @@ String for technical reasons, the semantic type is actually - Boolean -
Default value is: true + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean} +
Default value is: {@code true}
Since: Maven 3.6.1 ]]>
@@ -2085,8 +2085,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is true. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code true}. ]]> String @@ -2096,12 +2096,12 @@ The configuration as DOM object.

By default, every element content is trimmed, but starting with Maven 3.1.0, you can add - xml:space="preserve" to elements you want to preserve whitespace.

-

You can control how child POMs inherit configuration from parent POMs by adding combine.children - or combine.self attributes to the children of the configuration element:

+ {@code xml:space="preserve"} to elements you want to preserve whitespace.

+

You can control how child POMs inherit configuration from parent POMs by adding {@code combine.children} + or {@code combine.self} attributes to the children of the configuration element:

    -
  • combine.children: available values are merge (default) and append,
  • -
  • combine.self: available values are merge (default) and override.
  • +
  • {@code combine.children}: available values are {@code merge} (default) and {@code append},
  • +
  • {@code combine.self}: available values are {@code merge} (default) and {@code override}.

See POM Reference documentation and Xpp3DomUtils @@ -2133,7 +2133,7 @@ ConfigurationContainer <plugin> element contains informations required for a plugin. + The {@code } element contains informations required for a plugin. ]]> @@ -2165,8 +2165,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is false. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> @@ -2203,14 +2203,14 @@ private java.util.Map executionMap = null; /** - * Reset the executionMap field to null + * Reset the {@code executionMap} field to {@code null} */ public void flushExecutionMap() { this.executionMap = null; } /** - * @return a Map of executions field with PluginExecution#getId() as key + * @return a Map of executions field with {@code PluginExecution#getId()} as key * @see org.apache.maven.model.PluginExecution#getId() */ public java.util.Map getExecutionsAsMap() @@ -2250,7 +2250,7 @@ } /** - * @return the key of the plugin, ie groupId:artifactId + * @return the key of the plugin, ie {@code groupId:artifactId} */ public String getKey() { @@ -2260,7 +2260,7 @@ /** * @param groupId The group ID of the plugin in the repository * @param artifactId The artifact ID of the reporting plugin in the repository - * @return the key of the plugin, ie groupId:artifactId + * @return the key of the plugin, ie {@code groupId:artifactId} */ public static String constructKey( String groupId, String artifactId ) { @@ -2308,7 +2308,7 @@ ConfigurationContainer <execution> element contains informations required for the + The {@code } element contains informations required for the execution of a plugin. ]]> @@ -2407,8 +2407,8 @@ String for technical reasons, the semantic type is actually - Boolean. Default value is false. + of this field is {@code String} for technical reasons, the semantic type is actually + {@code Boolean}. Default value is {@code false}. ]]> @@ -2419,7 +2419,7 @@ ${project.build.directory}/site. + {@code ${project.build.directory}/site}. ]]> @@ -2544,9 +2544,9 @@ 1.4 only activates on JDKs versioned 1.4, - while !1.4 matches any JDK that is not version 1.4. Ranges are supported too: - [1.5,) activates when the JDK is 1.5 minimum. + For example, {@code 1.4} only activates on JDKs versioned 1.4, + while {@code !1.4} matches any JDK that is not version 1.4. Ranges are supported too: + {@code [1.5,)} activates when the JDK is 1.5 minimum. ]]> @@ -2625,7 +2625,7 @@ ${os.name} Java property, such as Windows XP. + of the {@code ${os.name}} Java property, such as {@code Windows XP}. ]]> @@ -2636,7 +2636,7 @@ windows or unix. + {@code windows} or {@code unix}. ]]> @@ -2659,11 +2659,11 @@ ActivationFile 4.0.0+ - missing value + exists will test for the existence of the file and if it is + activated. On the other hand, {@code exists} will test for the existence of the file and if it is there, the profile will be activated.
- Variable interpolation for these file specifications is limited to ${basedir}, + Variable interpolation for these file specifications is limited to {@code ${basedir}}, System properties and request properties.]]>
@@ -2712,7 +2712,7 @@ ConfigurationContainer <plugin> element in <reporting><plugins> contains informations required for a report plugin. + The {@code } element in {@code } contains informations required for a report plugin. ]]> @@ -2737,7 +2737,7 @@ build/plugins then in build/pluginManagement. + version is searched in {@code build/plugins} then in {@code build/pluginManagement}. ]]> String @@ -2748,7 +2748,7 @@ execution in the build. + configuration. This is the reporting parallel to an {@code execution} in the build. ]]> @@ -2765,7 +2765,7 @@ private java.util.Map reportSetMap = null; /** - * Reset the reportSetMap field to null + * Reset the {@code reportSetMap} field to {@code null} */ public void flushReportSetMap() { @@ -2773,7 +2773,7 @@ } /** - * @return a Map of reportSets field with ReportSet#getId() as key + * @return a Map of reportSets field with {@code ReportSet#getId()} as key * @see org.apache.maven.model.ReportSet#getId() */ public java.util.Map getReportSetsAsMap() @@ -2795,7 +2795,7 @@ } /** - * @return the key of the report plugin, ie groupId:artifactId + * @return the key of the report plugin, ie {@code groupId:artifactId} */ public String getKey() { @@ -2805,7 +2805,7 @@ /** * @param groupId The group ID of the plugin in the repository * @param artifactId The artifact ID of the reporting plugin in the repository - * @return the key of the report plugin, ie groupId:artifactId + * @return the key of the report plugin, ie {@code groupId:artifactId} */ public static String constructKey( String groupId, String artifactId ) { @@ -2868,12 +2868,12 @@ String 2.0 maven-plugin), the minimum version of + For a plugin project (packaging is {@code maven-plugin}), the minimum version of Maven required to use the resulting plugin.
In Maven 2, this was also specifying the minimum version of Maven required to build a project, but this usage is deprecated in Maven 3 and not checked any more: use the Maven Enforcer Plugin's - requireMavenVersion rule instead. + {@code requireMavenVersion} rule instead. ]]>
false From 73719e4b08863e0ea966dbec3e657f2de7378f46 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 5 Apr 2022 16:27:40 +0200 Subject: [PATCH 18/98] Add some javadoc to the model --- api/maven-api-model/src/main/mdo/model.vm | 63 ++++++++++++++++++++++- 1 file changed, 62 insertions(+), 1 deletion(-) diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 43752fc65699..6005b3aa06d3 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -95,6 +95,11 @@ package ${package}; import $imp; #end +/** +#foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} +#end + */ @Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) @@ -106,16 +111,30 @@ public class ${class.name} final String modelEncoding; #end #foreach ( $field in $class.allFields ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; #end #if ( ! $class.superClass ) - final Map locations; + /** Location of the xml element for this object. */ final InputLocation location; #end #foreach ( $field in $class.allFields ) + /** Location of the xml element for the field ${field.name}. */ final InputLocation ${field.name}Location; #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ ${class.name}( #if ( $class == $root ) String modelEncoding, @@ -205,6 +224,12 @@ public class ${class.name} #else #set ( $pfx = "get" ) #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end @@ -214,6 +239,9 @@ public class ${class.name} } #end + /** + * Gets the location of the specified field in the input source. + */ public InputLocation getLocation( Object key ) { if ( key instanceof String ) @@ -237,6 +265,9 @@ public class ${class.name} #end } + /** + * Creates a new builder with this object as the basis. + */ @Nonnull public Builder with() { @@ -245,6 +276,7 @@ public class ${class.name} #foreach ( $field in $allFields ) #set ( $cap = $Helper.capitalise( $field.name ) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** Creates a new ${class.name} instance using the specified ${field.name}. */ @Nonnull public ${class.name} with${cap}( $type $field.name ) { @@ -252,42 +284,71 @@ public class ${class.name} } #end + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ @Nonnull public static ${class.name} newInstance() { return newInstance( true ); } + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ @Nonnull public static ${class.name} newInstance( boolean withDefaults ) { return newBuilder( withDefaults ).build(); } + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ @Nonnull public static Builder newBuilder() { return newBuilder( true ); } + /** + * Creates a new ${class.name} builder instance using default values or not. + */ @Nonnull public static Builder newBuilder( boolean withDefaults ) { return new Builder( withDefaults ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ @Nonnull public static Builder newBuilder( ${class.name} from ) { return newBuilder( from, false ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ @Nonnull public static Builder newBuilder( ${class.name} from, boolean forceCopy ) { return new Builder( from, forceCopy ); } + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ @NotThreadSafe public static class Builder #if ( $class.superClass ) From f1700380d26e1eab459ecdce4fe6ef4bf03e2d6b Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 5 Apr 2022 16:30:26 +0200 Subject: [PATCH 19/98] Relax builders to use collections and leverage those --- api/maven-api-model/src/main/mdo/model.vm | 3 +++ .../DefaultDependencyManagementImporter.java | 3 +-- .../model/inheritance/DefaultInheritanceAssembler.java | 2 +- .../management/DefaultPluginManagementInjector.java | 2 +- .../org/apache/maven/model/merge/MavenModelMerger.java | 10 +++++----- .../model/normalization/DefaultModelNormalizer.java | 4 ++-- .../maven/model/profile/DefaultProfileInjector.java | 6 +++--- 7 files changed, 16 insertions(+), 14 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 6005b3aa06d3..77d2dff8c71f 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -276,6 +276,9 @@ public class ${class.name} #foreach ( $field in $allFields ) #set ( $cap = $Helper.capitalise( $field.name ) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end /** Creates a new ${class.name} instance using the specified ${field.name}. */ @Nonnull public ${class.name} with${cap}( $type $field.name ) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java index d14c2511db01..d817c99a919d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/composition/DefaultDependencyManagementImporter.java @@ -19,7 +19,6 @@ * under the License. */ -import java.util.ArrayList; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; @@ -76,7 +75,7 @@ public Model importManagement( Model target, List( dependencies.values() ) ) ); + depMgmt.withDependencies( dependencies.values() ) ); } return target; } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java index 6c9812c38bf5..20b3fc59cd24 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/inheritance/DefaultInheritanceAssembler.java @@ -356,7 +356,7 @@ protected void mergeReporting_Plugins( Reporting.Builder builder, merged.put( key, element ); } - builder.plugins( new ArrayList<>( merged.values() ) ); + builder.plugins( merged.values() ); } } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java index 2bb1113eb74c..62e3226f5342 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java @@ -139,7 +139,7 @@ protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Pl merged.put( key, element ); } - builder.executions( new ArrayList<>( merged.values() ) ); + builder.executions( merged.values() ); } } } 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 870fd972293b..a218c54c3715 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 @@ -220,7 +220,7 @@ protected void mergeModel_MailingLists( Model.Builder builder, Model target, Mod { if ( target.getMailingLists().isEmpty() ) { - builder.mailingLists( new ArrayList<>( source.getMailingLists() ) ); + builder.mailingLists( source.getMailingLists() ); } } @@ -296,7 +296,7 @@ protected void mergeModelBase_Repositories( ModelBase.Builder builder, ModelBase } } - builder.repositories( new ArrayList<>( merged.values() ) ); + builder.repositories( merged.values() ); } } @@ -337,7 +337,7 @@ protected void mergeModelBase_PluginRepositories( ModelBase.Builder builder, Mod } } - builder.pluginRepositories( new ArrayList<>( merged.values() ) ); + builder.pluginRepositories( merged.values() ); } } @@ -578,7 +578,7 @@ protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Pl merged.put( key, element ); } - builder.executions( new ArrayList<>( merged.values() ) ); + builder.executions( merged.values() ); } } @@ -636,7 +636,7 @@ protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, Repor merged.put( key, element ); } - builder.reportSets( new ArrayList<>( merged.values() ) ); + builder.reportSets( merged.values() ); } } 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 01bfe0d2718c..c56287c92fad 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 @@ -76,7 +76,7 @@ public Model mergeDuplicates( Model model, ModelBuildingRequest request, ModelPr if ( plugins.size() != normalized.size() ) { builder.build( Build.newBuilder( build ) - .plugins( new ArrayList<>( normalized.values() ) ) + .plugins( normalized.values() ) .build() ); } } @@ -98,7 +98,7 @@ public Model mergeDuplicates( Model model, ModelBuildingRequest request, ModelPr if ( dependencies.size() != normalized.size() ) { - builder.dependencies( new ArrayList<>( normalized.values() ) ); + builder.dependencies( normalized.values() ); } return builder.build(); diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java index 057ebb97e3ab..906954fa98ba 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java @@ -178,7 +178,7 @@ protected void mergePlugin_Executions( Plugin.Builder builder, Plugin target, Pl merged.put( key, element ); } - builder.executions( new ArrayList<>( merged.values() ) ); + builder.executions( merged.values() ); } } @@ -210,7 +210,7 @@ protected void mergeReporting_Plugins( Reporting.Builder builder, Reporting targ merged.put( key, element ); } - builder.plugins( new ArrayList<>( merged.values() ) ); + builder.plugins( merged.values() ); } } @@ -242,7 +242,7 @@ protected void mergeReportPlugin_ReportSets( ReportPlugin.Builder builder, Repor merged.put( key, element ); } - builder.reportSets( new ArrayList<>( merged.values() ) ); + builder.reportSets( merged.values() ); } } From c8507878a76dde8babb45b0f792da3ab3c6ed89e Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 5 Apr 2022 21:41:14 +0200 Subject: [PATCH 20/98] Use custom immutable lists --- .../api/model}/ImmutableCollections.java | 116 ++++++++++++++---- api/maven-api-model/src/main/mdo/model.vm | 24 ++-- 2 files changed, 110 insertions(+), 30 deletions(-) rename api/maven-api-model/src/main/{mdo => java/org/apache/maven/api/model}/ImmutableCollections.java (73%) diff --git a/api/maven-api-model/src/main/mdo/ImmutableCollections.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java similarity index 73% rename from api/maven-api-model/src/main/mdo/ImmutableCollections.java rename to api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java index d6fba9aab96b..56f46324ac82 100644 --- a/api/maven-api-model/src/main/mdo/ImmutableCollections.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java @@ -1,4 +1,4 @@ -package org.apache.maven.model; +package org.apache.maven.api.model; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,12 +19,12 @@ * under the License. */ -import java.lang.reflect.Array; import java.util.AbstractList; -import java.util.Arrays; import java.util.Collection; +import java.util.Collections; import java.util.Comparator; import java.util.Iterator; +import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; @@ -67,12 +67,16 @@ else if ( collection instanceof AbstractImmutableList ) return emptyList(); case 1: return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); default: - return (List) new ListN<>( collection ); + return new ListN<>( collection ); } } } + @SuppressWarnings( "unchecked" ) static List emptyList() { return ( List ) EMPTY_LIST; @@ -83,11 +87,46 @@ static List singletonList( E element ) return new List1<>( element ); } + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map.getClass().getDeclaringClass() == Collections.class ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return Collections.unmodifiableMap( new LinkedHashMap<>( map ) ); + } + } + } + + static Map emptyMap() + { + return Collections.emptyMap(); + } + + static Map singletonMap( K key, V value ) + { + return Collections.singletonMap( key, value ); + } + private static class List1 extends AbstractImmutableList { private final E element; - public List1( E element ) + private List1( E element ) { this.element = element; } @@ -109,20 +148,52 @@ public int size() } } + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + private static class ListN extends AbstractImmutableList { - private final E[] elements; + private final Object[] elements; private ListN( Collection elements ) { - E[] tmp = (E[]) Array.newInstance( elements.getClass().getComponentType(), elements.size() ); - this.elements = elements.toArray( tmp ); + this.elements = elements.toArray(); } + @SuppressWarnings( "unchecked" ) @Override public E get( int index ) { - return elements[ index ]; + return ( E ) elements[ index ]; } @Override @@ -132,7 +203,7 @@ public int size() } } - private static abstract class AbstractImmutableList extends AbstractList implements RandomAccess + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess { @Override public boolean add( E e ) @@ -191,13 +262,13 @@ public void sort( Comparator c ) @Override public Iterator iterator() { - return new Itr(); + return new Itr( 0 ); } @Override public ListIterator listIterator() { - return new Itr(); + return new Itr( 0 ); } @Override @@ -213,12 +284,18 @@ public ListIterator listIterator( int index ) @Override public List subList( int fromIndex, int toIndex ) { - if ( fromIndex < 0) + if ( fromIndex < 0 ) + { throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } if ( toIndex > size() ) + { throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } if ( fromIndex > toIndex ) + { throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } return new SubList( fromIndex, toIndex ); } @@ -227,12 +304,12 @@ protected IndexOutOfBoundsException outOfBounds( int index ) return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); } - class SubList extends AbstractImmutableList + private class SubList extends AbstractImmutableList { private final int fromIndex; private final int toIndex; - public SubList( int fromIndex, int toIndex ) + private SubList( int fromIndex, int toIndex ) { this.fromIndex = fromIndex; this.toIndex = toIndex; @@ -255,16 +332,11 @@ public int size() } } - class Itr implements ListIterator + private class Itr implements ListIterator { int index; - public Itr() - { - this.index = 0; - } - - public Itr( int index ) + private Itr( int index ) { this.index = index; } diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 77d2dff8c71f..da78aed64a3b 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -140,7 +140,11 @@ public class ${class.name} String modelEncoding, #end #foreach ( $field in $allFields ) - ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name, + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name, #end Map locations, InputLocation location, @@ -175,10 +179,18 @@ public class ${class.name} this.modelEncoding = modelEncoding; #end #foreach ( $field in $class.allFields ) + #if ( $field.type == "java.util.List" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #elseif ( $field.type == "java.util.Properties" ) + this.${field.name} = new ROProperties( ${field.name} ); + #elseif ( $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else this.${field.name} = ${field.name}; + #end #end #if ( ! $class.superClass ) - this.locations = locations; + this.locations = ImmutableCollections.copy( locations ); this.location = location; #end #foreach ( $field in $class.allFields ) @@ -471,17 +483,13 @@ public class ${class.name} modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), #end #foreach ( $field in $allFields ) - #if ( $field.type == "java.util.List" ) - ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() ), - #elseif ( $field.type == "java.util.Properties" ) - new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) ), - #elseif ( $field.type == "boolean" || $field.type == "int" ) + #if ( $field.type == "boolean" || $field.type == "int" ) ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} ), #else ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ), #end #end - Collections.unmodifiableMap( locations ), + locations, location != null ? location : ( base != null ? base.location : null ), #foreach ( $field in $allFields ) #if ( $field == ${allFields[${allFields.size()} - 1]} ) From 9eb92babccb17c73e11e5537a7d29f45ef86e095 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 Apr 2022 09:02:06 +0200 Subject: [PATCH 21/98] Add immutable maps and move ROProeprties as an inner class --- .../maven/api/model/ImmutableCollections.java | 349 +++++++++++++++++- .../apache/maven/api/model/ROProperties.java | 120 ------ api/maven-api-model/src/main/mdo/model.vm | 15 +- 3 files changed, 348 insertions(+), 136 deletions(-) delete mode 100644 api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java index 56f46324ac82..35c98d6e7e8e 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ImmutableCollections.java @@ -20,19 +20,24 @@ */ import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; import java.util.Collection; -import java.util.Collections; import java.util.Comparator; import java.util.Iterator; -import java.util.LinkedHashMap; import java.util.List; import java.util.ListIterator; import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; import java.util.function.Predicate; import java.util.function.UnaryOperator; -public class ImmutableCollections +class ImmutableCollections { private static final List EMPTY_LIST = new AbstractImmutableList() @@ -49,6 +54,39 @@ public int size() } }; + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + static List copy( Collection collection ) { if ( collection == null ) @@ -93,7 +131,7 @@ static Map copy( Map map ) { return emptyMap(); } - else if ( map.getClass().getDeclaringClass() == Collections.class ) + else if ( map instanceof AbstractImmutableMap ) { return map; } @@ -107,19 +145,29 @@ else if ( map.getClass().getDeclaringClass() == Collections.class ) Map.Entry entry = map.entrySet().iterator().next(); return singletonMap( entry.getKey(), entry.getValue() ); default: - return Collections.unmodifiableMap( new LinkedHashMap<>( map ) ); + return new MapN<>( map ); } } } + @SuppressWarnings( "unchecked" ) static Map emptyMap() { - return Collections.emptyMap(); + return ( Map ) EMPTY_MAP; } static Map singletonMap( K key, V value ) { - return Collections.singletonMap( key, value ); + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); } private static class List1 extends AbstractImmutableList @@ -397,7 +445,292 @@ public void add( E e ) } } - static UnsupportedOperationException uoe() + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Map.Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Map.Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() { return new UnsupportedOperationException(); } diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java deleted file mode 100644 index 9de3eb443f19..000000000000 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/ROProperties.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.apache.maven.api.model; - -/* - * 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. - */ - -import java.util.Map; -import java.util.Properties; -import java.util.function.BiFunction; -import java.util.function.Function; - -class ROProperties extends Properties -{ - ROProperties( Properties props ) - { - super(); - if ( props != null ) - { - // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException - for ( Map.Entry e : props.entrySet() ) - { - super.put( e.getKey(), e.getValue() ); - } - } - } - - @Override - public Object put( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object remove( Object key ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void putAll( Map t ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void clear() - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void replaceAll( BiFunction function ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object putIfAbsent( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public boolean remove( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public boolean replace( Object key, Object oldValue, Object newValue ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object replace( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object computeIfAbsent( Object key, Function mappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object computeIfPresent( Object key, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object compute( Object key, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object merge( Object key, Object value, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - -} diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index da78aed64a3b..52562301988c 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -179,11 +179,7 @@ public class ${class.name} this.modelEncoding = modelEncoding; #end #foreach ( $field in $class.allFields ) - #if ( $field.type == "java.util.List" ) - this.${field.name} = ImmutableCollections.copy( ${field.name} ); - #elseif ( $field.type == "java.util.Properties" ) - this.${field.name} = new ROProperties( ${field.name} ); - #elseif ( $field.type == "java.util.Map" ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) this.${field.name} = ImmutableCollections.copy( ${field.name} ); #else this.${field.name} = ${field.name}; @@ -454,11 +450,14 @@ public class ${class.name} @Nonnull public Builder location( Object key, InputLocation location ) { - if ( this.locations == null ) + if ( location != null ) { - this.locations = new HashMap<>(); + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); } - this.locations.put( key, location ); return this; } From e9d7ffd4dcde13ccc17fd90016fd2d28d7a316ed Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 Apr 2022 10:43:00 +0200 Subject: [PATCH 22/98] Fix writing integers and default values --- maven-model/src/main/mdo/writer.vm | 62 ++++++++++++++------ maven-settings/src/main/mdo/writer.vm | 17 ++++-- maven-toolchain-model/src/main/mdo/writer.vm | 13 ++-- 3 files changed, 64 insertions(+), 28 deletions(-) diff --git a/maven-model/src/main/mdo/writer.vm b/maven-model/src/main/mdo/writer.vm index 8d6c18ea7303..94cb6ce56e07 100644 --- a/maven-model/src/main/mdo/writer.vm +++ b/maven-model/src/main/mdo/writer.vm @@ -19,6 +19,15 @@ #set ( $basePackage = "org.apache.maven.api.model" ) #set ( $package = "org.apache.maven.model.v4" ) #set ( $className = "MavenXpp3Writer" ) +#foreach ( $class in $model.allClasses ) + #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) + #set ( $root = $class ) + #end +#end +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java package ${package}; @@ -90,17 +99,17 @@ public class ${className} * @param model a model object. * @throws java.io.IOException java.io.IOException if any. */ - public void write( Writer writer, Model model ) + public void write( Writer writer, ${root.name} ${rootLcapName} ) throws java.io.IOException { XmlSerializer serializer = new MXSerializer(); serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); serializer.setOutput( writer ); - serializer.startDocument( model.getModelEncoding(), null ); - writeModel( "project", model, serializer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); serializer.endDocument(); - } //-- void write( Writer, Model ) + } //-- void write( Writer, ${root.name} ) /** * Method write. @@ -109,17 +118,17 @@ public class ${className} * @param model a model object. * @throws java.io.IOException java.io.IOException if any. */ - public void write( OutputStream stream, Model model ) + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) throws java.io.IOException { XmlSerializer serializer = new MXSerializer(); serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); - serializer.setOutput( stream, model.getModelEncoding() ); - serializer.startDocument( model.getModelEncoding(), null ); - writeModel( "project", model, serializer ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); serializer.endDocument(); - } //-- void write( OutputStream, Model ) + } //-- void write( OutputStream, ${root.name} ) /** * Method writeDomToSerializer. @@ -193,28 +202,33 @@ public class ${className} #set ( $fieldTagName = $field.name ) #end #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) #if ( $field.type == "String" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - #if ( ${field.defaultValue} == "true" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); #else - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); #end #elseif ( $field.type == "int" ) - // TODO: name=${field.name} type=${field.type} + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); #elseif ( $field.type == "DOM" ) writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) #set( $singularField = ${Helper.singular($fieldTagName)} ) - writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.to && $field.multiplicity == "1" ) write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.to && $field.multiplicity == "*" ) #set( $singularField = ${Helper.singular($fieldTagName)} ) - writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, t -> write${field.to}( "$singularField", t, serializer ) ); #else // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end @@ -234,15 +248,27 @@ public class ${className} private void writeList( String tagName, List list, XmlSerializer serializer, ElementWriter writer ) throws IOException + { + writeList( tagName, false, list, serializer, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, ElementWriter writer ) + throws IOException { if ( list != null && !list.isEmpty() ) { - serializer.startTag( NAMESPACE, tagName ); + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } for ( T t : list ) { writer.write( t ); } - serializer.endTag( NAMESPACE, tagName ); + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + } } } diff --git a/maven-settings/src/main/mdo/writer.vm b/maven-settings/src/main/mdo/writer.vm index 007ba93384ed..c65b25628647 100644 --- a/maven-settings/src/main/mdo/writer.vm +++ b/maven-settings/src/main/mdo/writer.vm @@ -202,21 +202,26 @@ public class ${className} #set ( $fieldTagName = $field.name ) #end #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) #if ( $field.type == "String" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - #if ( ${field.defaultValue} == "true" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); #else - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); #end #elseif ( $field.type == "int" ) - // TODO: name=${field.name} type=${field.type} + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); #elseif ( $field.type == "DOM" ) writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) #set( $singularField = ${Helper.singular($fieldTagName)} ) - writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.to && $field.multiplicity == "1" ) diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm index 41ee68060eae..3aea696d78be 100644 --- a/maven-toolchain-model/src/main/mdo/writer.vm +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -202,16 +202,21 @@ public class ${className} #set ( $fieldTagName = $field.name ) #end #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) #if ( $field.type == "String" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) #if ( ${field.defaultValue} == "true" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); #else - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); #end #elseif ( $field.type == "int" ) - // TODO: name=${field.name} type=${field.type} + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); #elseif ( $field.type == "DOM" ) writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) From a5cebd1ed06ce937532e5939706e6f03704f6f5c Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 Apr 2022 10:43:14 +0200 Subject: [PATCH 23/98] Remove duplicate call --- .../org/apache/maven/settings/merge/MavenSettingsMerger.java | 1 - 1 file changed, 1 deletion(-) 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 c6d3b1827928..69e8a35f0896 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 @@ -106,7 +106,6 @@ private static List shallowMergeById( merged.add( identifiable ); } } - merged.addAll( dominant ); return merged; } From 8b15e36d3d2c587c6eac3eddf2ca8e4ad05276b9 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 Apr 2022 11:51:22 +0200 Subject: [PATCH 24/98] Fix profile injection --- .../org/apache/maven/model/profile/DefaultProfileInjector.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java index 906954fa98ba..1196acce9f3b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java @@ -68,8 +68,8 @@ public Model injectProfile( Model model, Profile profile, ModelBuildingRequest r if ( profile.getBuild() != null ) { - Build.Builder bbuilder = Build.newBuilder(); Build build = model.getBuild() != null ? model.getBuild() : Build.newInstance(); + Build.Builder bbuilder = Build.newBuilder( build ); merger.mergeBuildBase( bbuilder, build, profile.getBuild() ); builder.build( bbuilder.build() ); } From 006a92cf2bd6399393d09588feb944bda91d5fa8 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 Apr 2022 11:51:33 +0200 Subject: [PATCH 25/98] Fix xpp3 dom wrapping --- maven-model-builder/pom.xml | 5 ++ .../org/codehaus/plexus/util/xml/Xpp3Dom.java | 69 ++++++++++++------- 2 files changed, 51 insertions(+), 23 deletions(-) diff --git a/maven-model-builder/pom.xml b/maven-model-builder/pom.xml index 27ec86f331c1..d03c3b04d31a 100644 --- a/maven-model-builder/pom.xml +++ b/maven-model-builder/pom.xml @@ -34,6 +34,11 @@ under the License. The effective model builder, with inheritance, profile activation, interpolation, ... + + org.apache.maven + maven-xml-impl + 4.0.0-alpha-1-SNAPSHOT + org.codehaus.plexus plexus-utils diff --git a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java index bf82963a955f..0330c17b6f5f 100644 --- a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java +++ b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java @@ -69,6 +69,7 @@ public class Xpp3Dom */ public static final String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE; + private Xpp3Dom parent; private Dom dom; public Xpp3Dom( String name ) @@ -103,12 +104,18 @@ public Xpp3Dom( Xpp3Dom src ) public Xpp3Dom( Xpp3Dom src, String name ) { this.dom = new org.apache.maven.internal.xml.Xpp3Dom( src.dom, name ); - } + } - public Xpp3Dom( Dom dom ) - { - this.dom = dom; - } + public Xpp3Dom( Dom dom ) + { + this.dom = dom; + } + + public Xpp3Dom( Dom dom, Xpp3Dom parent ) + { + this.dom = dom; + this.parent = parent; + } public Dom getDom() { @@ -135,8 +142,8 @@ public String getValue() public void setValue( String value ) { - this.dom = new org.apache.maven.internal.xml.Xpp3Dom( - dom.getName(), value, dom.getAttributes(), dom.getChildren(), dom.getInputLocation() ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), value, dom.getAttributes(), dom.getChildren(), dom.getInputLocation() ) ); } // ---------------------------------------------------------------------- @@ -167,8 +174,8 @@ public boolean removeAttribute( String name ) boolean ret = attrs.remove( name ) != null; if ( ret ) { - this.dom = new org.apache.maven.internal.xml.Xpp3Dom( - dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ) ); } return ret; } @@ -193,8 +200,8 @@ public void setAttribute( String name, String value ) } Map attrs = new HashMap<>( dom.getAttributes() ); attrs.put( name, value ); - this.dom = new org.apache.maven.internal.xml.Xpp3Dom( - dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), attrs, dom.getChildren(), dom.getInputLocation() ) ); } // ---------------------------------------------------------------------- @@ -203,34 +210,34 @@ public void setAttribute( String name, String value ) public Xpp3Dom getChild( int i ) { - return new Xpp3Dom( dom.getChildren().get( i ) ); + return new Xpp3Dom( dom.getChildren().get( i ), this ); } public Xpp3Dom getChild( String name ) { Dom child = dom.getChild( name ); - return child != null ? new Xpp3Dom( child ) : null; + return child != null ? new Xpp3Dom( child, this ) : null; } public void addChild( Xpp3Dom xpp3Dom ) { List children = new ArrayList<>( dom.getChildren() ); children.add( xpp3Dom.dom ); - this.dom = new org.apache.maven.internal.xml.Xpp3Dom( - dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); } public Xpp3Dom[] getChildren() { return dom.getChildren().stream() - .map( Xpp3Dom::new ).toArray( Xpp3Dom[]::new ); + .map( d -> new Xpp3Dom( d, this ) ).toArray( Xpp3Dom[]::new ); } public Xpp3Dom[] getChildren( String name ) { return dom.getChildren().stream() .filter( c -> c.getName().equals( name ) ) - .map( Xpp3Dom::new ).toArray( Xpp3Dom[]::new ); + .map( d -> new Xpp3Dom( d, this ) ).toArray( Xpp3Dom[]::new ); } public int getChildCount() @@ -242,16 +249,16 @@ public void removeChild( int i ) { List children = new ArrayList<>( dom.getChildren() ); children.remove( i ); - this.dom = new org.apache.maven.internal.xml.Xpp3Dom( - dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); } public void removeChild( Xpp3Dom child ) { List children = new ArrayList<>( dom.getChildren() ); children.remove( child.dom ); - this.dom = new org.apache.maven.internal.xml.Xpp3Dom( - dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); } // ---------------------------------------------------------------------- @@ -286,8 +293,8 @@ public Object getInputLocation() */ public void setInputLocation( Object inputLocation ) { - this.dom = new org.apache.maven.internal.xml.Xpp3Dom( - dom.getName(), dom.getValue(), dom.getAttributes(), dom.getChildren(), inputLocation ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), dom.getChildren(), inputLocation ) ); } // ---------------------------------------------------------------------- @@ -443,4 +450,20 @@ public static boolean isEmpty( String str ) return ( ( str == null ) || ( str.trim().length() == 0 ) ); } + private void update( Dom dom ) + { + if ( parent != null ) + { + parent.replace( this.dom, dom ); + } + this.dom = dom; + } + + private void replace( Dom prevChild, Dom newChild ) + { + List children = new ArrayList<>( dom.getChildren() ); + children.replaceAll( d -> d == prevChild ? newChild : d ); + update( new org.apache.maven.internal.xml.Xpp3Dom( + dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); + } } From b973df7776fba71549ee83021e462b04e3e5e1ef Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 Apr 2022 16:49:01 +0200 Subject: [PATCH 26/98] Fix xml node interpolation --- maven-model/src/main/mdo/transformer.vm | 45 +++++++++++++++++++++++++ 1 file changed, 45 insertions(+) diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm index 83e6c290003f..621c0eb0a200 100644 --- a/maven-model/src/main/mdo/transformer.vm +++ b/maven-model/src/main/mdo/transformer.vm @@ -39,9 +39,11 @@ import java.util.function.Function; import java.util.stream.Collectors; import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.xml.Dom; #foreach ( $class in $model.allClasses ) import ${basePackage}.${class.name}; #end +import org.codehaus.plexus.util.xml.Xpp3Dom; @Generated public class ${className} @@ -125,6 +127,9 @@ public class ${className} builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); #elseif ( $field.to && $field.multiplicity == "*" ) builder.${field.name}( transform( target.get${capField}(), this::transform${field.to} ) ); + #elseif ( $field.type == "DOM" ) + Dom newVal = transform( target.get${capField}() ); + builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end @@ -151,4 +156,44 @@ public class ${className} return newList; } + protected Dom transform( Dom node ) + { + if ( node != null ) + { + Xpp3Dom xpp = new Xpp3Dom( node ); + transform( xpp ); + return xpp.getDom(); + } + return node; + } + + protected void transform( Xpp3Dom dom ) + { + if ( dom != null ) + { + String org, val; + // Content + org = dom.getValue(); + val = transform( org ); + if ( org != val ) + { + dom.setValue( val ); + } + // Attributes + for ( String attr : dom.getAttributeNames() ) + { + org = dom.getAttribute( attr ); + val = transform( org ); + if ( org != val ) + { + dom.setAttribute( attr, val ); + } + } + // Children + for ( int i = 0, l = dom.getChildCount(); i < l; i++ ) + { + transform( dom.getChild( i ) ); + } + } + } } From db77d15037c6852899c048a1acabb0d061d90a62 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 6 Apr 2022 23:22:50 +0200 Subject: [PATCH 27/98] Introduce a mechanism to track changes and update the mutable model accordingly --- .../internal/DefaultMavenPluginManager.java | 3 +- .../org/apache/maven/model/BaseObject.java | 68 +++++++++++++++++++ maven-model/src/main/mdo/model-v3.vm | 68 +++++++++++-------- 3 files changed, 109 insertions(+), 30 deletions(-) create mode 100644 maven-model/src/main/java/org/apache/maven/model/BaseObject.java diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 707c6d8ce2d5..59f83ca4b094 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -590,7 +590,8 @@ else if ( cause instanceof LinkageError ) ( (Mojo) mojo ).setLog( new MojoLogWrapper( mojoLogger ) ); } - Dom dom = mojoExecution.getConfiguration().getDom(); + Dom dom = mojoExecution.getConfiguration() != null + ? mojoExecution.getConfiguration().getDom() : null; PlexusConfiguration pomConfiguration; diff --git a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java new file mode 100644 index 000000000000..ebac403256b6 --- /dev/null +++ b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java @@ -0,0 +1,68 @@ +package org.apache.maven.model; + +/* + * 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. + */ + +import java.io.Serializable; + +public abstract class BaseObject + implements Serializable, Cloneable, InputLocationTracker +{ + protected BaseObject parent; + protected Object delegate; + + public BaseObject() + { + } + + public BaseObject( Object delegate, BaseObject parent ) + { + this.delegate = delegate; + this.parent = parent; + } + + public Object getDelegate() + { + return delegate; + } + + public BaseObject getParent() + { + return parent; + } + + public void setParent( BaseObject parent ) + { + this.parent = parent; + } + + protected void update( Object newDelegate ) + { + if ( delegate != newDelegate ) + { + if ( parent != null ) + { + parent.replace( delegate, newDelegate ); + } + delegate = newDelegate; + } + } + + protected abstract void replace( Object oldDelegate, Object newDelegate ); +} diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 488ebd807614..0d8d4082e37d 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -91,13 +91,11 @@ import $imp; public class ${class.name} #if ( $class.superClass ) extends ${class.superClass} - #end implements Serializable, Cloneable -{ - - #if ( ! $class.superClass ) - org.apache.maven.api.model.${class.name} delegate; + #else + extends BaseObject #end +{ public ${class.name}() { @@ -106,11 +104,12 @@ public class ${class.name} public ${class.name}( org.apache.maven.api.model.${class.name} delegate ) { - #if ( $class.superClass ) - super( delegate ); - #else - this.delegate = delegate; - #end + this( delegate, null ); + } + + public ${class.name}( org.apache.maven.api.model.${class.name} delegate, BaseObject parent ) + { + super( delegate, parent ); } public ${class.name} clone() @@ -123,11 +122,7 @@ public class ${class.name} #end public org.apache.maven.api.model.${class.name} getDelegate() { - #if ( $class.superClass ) - return ( org.apache.maven.api.model.${class.name} ) delegate; - #else - return delegate; - #end + return ( org.apache.maven.api.model.${class.name} ) super.getDelegate(); } #if ( ! $eq.empty ) @@ -175,14 +170,14 @@ public class ${class.name} { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) return new WrapperList<${field.to}, org.apache.maven.api.model.${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} ); #elseif ( $field.to == "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) return new WrapperList( 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 org.codehaus.plexus.util.xml.Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; #else @@ -200,18 +195,18 @@ public class ${class.name} org.apache.maven.api.xml.Dom dom = ( org.apache.maven.api.xml.Dom ) ${field.name}; if ( ! Objects.equals( dom, getDelegate().${pfx}${cap}() ) ) { - delegate = getDelegate().with${cap}( dom ); + update( getDelegate().with${cap}( dom ) ); } #else if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - delegate = getDelegate().with${cap}( - ${field.name}.stream().map( c -> c.getDelegate() ).collect( Collectors.toList() ) ); + update( 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() ); + update( getDelegate().with${cap}( ${field.name}.getDelegate() ) ); #else - delegate = getDelegate().with${cap}( ${field.name} ); + update( getDelegate().with${cap}( ${field.name} ) ); #end } #end @@ -223,13 +218,13 @@ 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() ) ) ); #end } @@ -243,8 +238,23 @@ public class ${class.name} public void setLocation( Object key, InputLocation location ) { - delegate = org.apache.maven.api.model.${class.name}.newBuilder( getDelegate(), true ) - .location( key, location.toApiLocation() ).build(); + update( org.apache.maven.api.model.${class.name}.newBuilder( getDelegate(), true ) + .location( key, location.toApiLocation() ).build() ); + } + + protected void replace( Object oldDelegate, Object newDelegate ) + { + #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}( ( org.apache.maven.api.model.${field.to} ) newDelegate ) ); + return; + } + #end + #end } public static List ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) From 92f1f68dc70a72e6cafb4f2c65d27cd10a44ea7b Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 09:47:26 +0200 Subject: [PATCH 28/98] Fix tracking mechanism for lists --- .../java/org/apache/maven/model/BaseObject.java | 5 ++++- maven-model/src/main/mdo/model-v3.vm | 17 +++++++++++++++-- 2 files changed, 19 insertions(+), 3 deletions(-) diff --git a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java index ebac403256b6..9c583b6839d2 100644 --- a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java +++ b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java @@ -64,5 +64,8 @@ protected void update( Object newDelegate ) } } - protected abstract void replace( Object oldDelegate, Object newDelegate ); + protected boolean replace( Object oldDelegate, Object newDelegate ) + { + return false; + } } diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 0d8d4082e37d..1b8439f5c6f3 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -242,8 +242,12 @@ public class ${class.name} .location( key, location.toApiLocation() ).build() ); } - protected void replace( Object oldDelegate, Object newDelegate ) + 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)})} ) @@ -251,10 +255,19 @@ public class ${class.name} if ( oldDelegate == getDelegate().get${cap}() ) { update( getDelegate().with${cap}( ( org.apache.maven.api.model.${field.to} ) newDelegate ) ); - return; + return true; + } + #elseif ( $field.type == "java.util.List" && $field.to != "String" ) + if ( getDelegate().get${cap}().contains( oldDelegate ) ) + { + List list = new ArrayList<>( getDelegate().get${cap}() ); + list.replaceAll( d -> d == oldDelegate ? ( org.apache.maven.api.model.${field.to} ) newDelegate : d ); + update( getDelegate().with${cap}( list ) ); + return true; } #end #end + return false; } public static List ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) From 007e01bb02115d0e0118355fa5e4f040d0478c88 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 10:24:52 +0200 Subject: [PATCH 29/98] Reconcile some differences between the model templates --- api/maven-api-model/pom.xml | 3 +++ api/maven-api-model/src/main/mdo/model.vm | 17 ++++++++++------- api/maven-api-settings/pom.xml | 3 +++ api/maven-api-settings/src/main/mdo/model.vm | 16 +++++++++------- api/maven-api-toolchain/pom.xml | 3 +++ api/maven-api-toolchain/src/main/mdo/model.vm | 17 +++++++++-------- 6 files changed, 37 insertions(+), 22 deletions(-) diff --git a/api/maven-api-model/pom.xml b/api/maven-api-model/pom.xml index ed5b439e7e02..c780cdf04e50 100644 --- a/api/maven-api-model/pom.xml +++ b/api/maven-api-model/pom.xml @@ -76,6 +76,9 @@ under the License. + + basePackage=org.apache.maven.api.model + diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 52562301988c..efa2142140f2 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -16,14 +16,18 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.model" ) -#set ( $package = "${basePackage}" ) +## +## The following loop code is required in order to change the type of the +## pomFile attribute to a java.nio.file.Path. Modello does not support this +## type and loading a model with such a type would fail the modello validation. +## #foreach ( $field in $model.getClass("Model", $version).allFields ) #if ( $field.name == "pomFile" ) #set ( $dummy = $field.setType("java.nio.file.Path") ) #end #end # +#set ( $package = "${basePackage}" ) #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) #set ( $allFields = [] ) @@ -37,11 +41,7 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end - #end + #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) @@ -89,6 +89,9 @@ #end #end #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; #foreach ( $imp in $imports ) diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml index 93a5abf2c319..617f6f2eb004 100644 --- a/api/maven-api-settings/pom.xml +++ b/api/maven-api-settings/pom.xml @@ -76,6 +76,9 @@ under the License. + + basePackage=org.apache.maven.api.settings + diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm index 19bba531bf0d..e18dbeca91de 100644 --- a/api/maven-api-settings/src/main/mdo/model.vm +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -16,7 +16,7 @@ specific language governing permissions and limitations under the License. *# -#set ( $package = "org.apache.maven.api.settings" ) +#set ( $package = "${basePackage}" ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -30,12 +30,8 @@ #end #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end - #end - #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) + #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) #set ( $dummy = $imports.add( "java.util.Collections" ) ) @@ -48,6 +44,9 @@ #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) #set ( $dummy = $imports.add( "java.util.List" ) ) #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) #else #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) #set ( $idx = $fieldType.lastIndexOf('.') ) @@ -75,6 +74,9 @@ #end #end #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; #foreach ( $imp in $imports ) diff --git a/api/maven-api-toolchain/pom.xml b/api/maven-api-toolchain/pom.xml index 29dd242e2112..4107d3ef4d85 100644 --- a/api/maven-api-toolchain/pom.xml +++ b/api/maven-api-toolchain/pom.xml @@ -77,6 +77,9 @@ under the License. + + basePackage=org.apache.maven.api.toolchain + diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm index b3bdc9e25365..e18dbeca91de 100644 --- a/api/maven-api-toolchain/src/main/mdo/model.vm +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -16,8 +16,7 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.toolchain" ) -#set ( $package = "$basePackage" ) +#set ( $package = "${basePackage}" ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -31,12 +30,8 @@ #end #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end - #end - #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) + #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) #set ( $dummy = $imports.add( "java.util.Collections" ) ) @@ -49,6 +44,9 @@ #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) #set ( $dummy = $imports.add( "java.util.List" ) ) #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) #else #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) #set ( $idx = $fieldType.lastIndexOf('.') ) @@ -76,6 +74,9 @@ #end #end #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; #foreach ( $imp in $imports ) From 57330751d26ddb84b8dbc88f9a89a6c3626da846 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 13:50:36 +0200 Subject: [PATCH 30/98] Add a header to generated files --- maven-model/src/main/mdo/merger.vm | 3 +++ maven-model/src/main/mdo/model-v3.vm | 3 +++ maven-model/src/main/mdo/reader-ex.vm | 3 +++ maven-model/src/main/mdo/reader.vm | 3 +++ maven-model/src/main/mdo/transformer.vm | 3 +++ maven-model/src/main/mdo/writer-ex.vm | 3 +++ maven-model/src/main/mdo/writer.vm | 3 +++ maven-plugin-api/src/main/mdo/merger.vm | 3 +++ maven-plugin-api/src/main/mdo/model.vm | 3 +++ maven-plugin-api/src/main/mdo/reader.vm | 3 +++ maven-plugin-api/src/main/mdo/writer.vm | 3 +++ maven-settings/src/main/mdo/merger.vm | 3 +++ maven-settings/src/main/mdo/model-v3.vm | 3 +++ maven-settings/src/main/mdo/reader.vm | 3 +++ maven-settings/src/main/mdo/writer.vm | 3 +++ maven-toolchain-model/src/main/mdo/merger.vm | 3 +++ maven-toolchain-model/src/main/mdo/model-v3.vm | 3 +++ maven-toolchain-model/src/main/mdo/reader.vm | 3 +++ maven-toolchain-model/src/main/mdo/writer.vm | 3 +++ 19 files changed, 57 insertions(+) diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm index 7b2a78f8639c..9b2bd0d06193 100644 --- a/maven-model/src/main/mdo/merger.vm +++ b/maven-model/src/main/mdo/merger.vm @@ -26,6 +26,9 @@ #end # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.ObjectStreamException; diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 1b8439f5c6f3..71abe91b9cec 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -81,6 +81,9 @@ #end #end #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; #foreach ( $imp in $imports ) diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm index 6fd161f10b45..4ae636d4af05 100644 --- a/maven-model/src/main/mdo/reader-ex.vm +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -21,6 +21,9 @@ #set ( $className = "MavenXpp3ReaderEx" ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm index f91fc866ba87..2c7604a192bc 100644 --- a/maven-model/src/main/mdo/reader.vm +++ b/maven-model/src/main/mdo/reader.vm @@ -21,6 +21,9 @@ #set ( $className = "MavenXpp3Reader" ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm index 621c0eb0a200..f046c1640851 100644 --- a/maven-model/src/main/mdo/transformer.vm +++ b/maven-model/src/main/mdo/transformer.vm @@ -21,6 +21,9 @@ #set ( $className = "ModelTransformer" ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.ObjectStreamException; diff --git a/maven-model/src/main/mdo/writer-ex.vm b/maven-model/src/main/mdo/writer-ex.vm index da414d8e5858..5a98d8a5664e 100644 --- a/maven-model/src/main/mdo/writer-ex.vm +++ b/maven-model/src/main/mdo/writer-ex.vm @@ -21,6 +21,9 @@ #set ( $className = "MavenXpp3WriterEx" ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import org.apache.maven.api.annotations.Generated; diff --git a/maven-model/src/main/mdo/writer.vm b/maven-model/src/main/mdo/writer.vm index 94cb6ce56e07..7f126b0792a2 100644 --- a/maven-model/src/main/mdo/writer.vm +++ b/maven-model/src/main/mdo/writer.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-plugin-api/src/main/mdo/merger.vm b/maven-plugin-api/src/main/mdo/merger.vm index b29d8d5a68ad..38c3614c489c 100644 --- a/maven-plugin-api/src/main/mdo/merger.vm +++ b/maven-plugin-api/src/main/mdo/merger.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.ObjectStreamException; diff --git a/maven-plugin-api/src/main/mdo/model.vm b/maven-plugin-api/src/main/mdo/model.vm index 2cf6778df784..01cb619fedd0 100644 --- a/maven-plugin-api/src/main/mdo/model.vm +++ b/maven-plugin-api/src/main/mdo/model.vm @@ -75,6 +75,9 @@ #end #end #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; #foreach ( $imp in $imports ) diff --git a/maven-plugin-api/src/main/mdo/reader.vm b/maven-plugin-api/src/main/mdo/reader.vm index 5799f516d462..68ef95cad8dd 100644 --- a/maven-plugin-api/src/main/mdo/reader.vm +++ b/maven-plugin-api/src/main/mdo/reader.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-plugin-api/src/main/mdo/writer.vm b/maven-plugin-api/src/main/mdo/writer.vm index 8de89ee6fc80..80803fc61b47 100644 --- a/maven-plugin-api/src/main/mdo/writer.vm +++ b/maven-plugin-api/src/main/mdo/writer.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-settings/src/main/mdo/merger.vm b/maven-settings/src/main/mdo/merger.vm index 6056f0c75850..10a66c17d84b 100644 --- a/maven-settings/src/main/mdo/merger.vm +++ b/maven-settings/src/main/mdo/merger.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.ObjectStreamException; diff --git a/maven-settings/src/main/mdo/model-v3.vm b/maven-settings/src/main/mdo/model-v3.vm index 9cbec77ec3e9..e4f84cd0d022 100644 --- a/maven-settings/src/main/mdo/model-v3.vm +++ b/maven-settings/src/main/mdo/model-v3.vm @@ -81,6 +81,9 @@ #end #end #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; #foreach ( $imp in $imports ) diff --git a/maven-settings/src/main/mdo/reader.vm b/maven-settings/src/main/mdo/reader.vm index 6cc754abe49a..533eaf84d2eb 100644 --- a/maven-settings/src/main/mdo/reader.vm +++ b/maven-settings/src/main/mdo/reader.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-settings/src/main/mdo/writer.vm b/maven-settings/src/main/mdo/writer.vm index c65b25628647..5e3892c66986 100644 --- a/maven-settings/src/main/mdo/writer.vm +++ b/maven-settings/src/main/mdo/writer.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-toolchain-model/src/main/mdo/merger.vm b/maven-toolchain-model/src/main/mdo/merger.vm index 63c3deab00d1..8deefff1c269 100644 --- a/maven-toolchain-model/src/main/mdo/merger.vm +++ b/maven-toolchain-model/src/main/mdo/merger.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.ObjectStreamException; diff --git a/maven-toolchain-model/src/main/mdo/model-v3.vm b/maven-toolchain-model/src/main/mdo/model-v3.vm index bc32573d1fb3..15bc43d9ce1f 100644 --- a/maven-toolchain-model/src/main/mdo/model-v3.vm +++ b/maven-toolchain-model/src/main/mdo/model-v3.vm @@ -81,6 +81,9 @@ #end #end #end +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; #foreach ( $imp in $imports ) diff --git a/maven-toolchain-model/src/main/mdo/reader.vm b/maven-toolchain-model/src/main/mdo/reader.vm index df8ecf62d0c4..2634e8b85056 100644 --- a/maven-toolchain-model/src/main/mdo/reader.vm +++ b/maven-toolchain-model/src/main/mdo/reader.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm index 3aea696d78be..da5cce3e99f1 100644 --- a/maven-toolchain-model/src/main/mdo/writer.vm +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -30,6 +30,9 @@ #set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java +// =================== DO NOT EDIT THIS FILE ==================== +// Generated by Maven, any modifications will be overwritten. +// ============================================================== package ${package}; import java.io.IOException; From d5cbb00da32bcaac8fef54e90b57f252f9d7382b Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 13:58:57 +0200 Subject: [PATCH 31/98] Retrieve root model class in a cleaner way --- api/maven-api-model/src/main/mdo/model.vm | 2 +- api/maven-api-settings/src/main/mdo/model.vm | 2 +- api/maven-api-toolchain/src/main/mdo/model.vm | 2 +- maven-model/src/main/mdo/model-v3.vm | 6 +----- maven-model/src/main/mdo/reader-ex.vm | 14 +++++--------- maven-model/src/main/mdo/reader.vm | 14 +++++--------- maven-model/src/main/mdo/writer.vm | 6 +----- maven-plugin-api/src/main/mdo/merger.vm | 6 +----- maven-plugin-api/src/main/mdo/model.vm | 6 +----- maven-plugin-api/src/main/mdo/reader.vm | 6 +----- maven-plugin-api/src/main/mdo/writer.vm | 6 +----- maven-settings/src/main/mdo/merger.vm | 6 +----- maven-settings/src/main/mdo/model-v3.vm | 6 +----- maven-settings/src/main/mdo/reader.vm | 6 +----- maven-settings/src/main/mdo/writer.vm | 6 +----- maven-toolchain-model/src/main/mdo/merger.vm | 6 +----- maven-toolchain-model/src/main/mdo/model-v3.vm | 6 +----- maven-toolchain-model/src/main/mdo/reader.vm | 6 +----- maven-toolchain-model/src/main/mdo/writer.vm | 6 +----- 19 files changed, 27 insertions(+), 91 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index efa2142140f2..75cf96b89f99 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -28,6 +28,7 @@ #end # #set ( $package = "${basePackage}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) #set ( $allFields = [] ) @@ -41,7 +42,6 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm index e18dbeca91de..fbcdeed02895 100644 --- a/api/maven-api-settings/src/main/mdo/model.vm +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -17,6 +17,7 @@ under the License. *# #set ( $package = "${basePackage}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -30,7 +31,6 @@ #end #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm index e18dbeca91de..fbcdeed02895 100644 --- a/api/maven-api-toolchain/src/main/mdo/model.vm +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -17,6 +17,7 @@ under the License. *# #set ( $package = "${basePackage}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -30,7 +31,6 @@ #end #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 71abe91b9cec..e4fc1c7471f5 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -18,6 +18,7 @@ *# #set ( $basePackage = "org.apache.maven.model" ) #set ( $package = "${basePackage}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -32,11 +33,6 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end - #end #set ( $types = { "DOM": "Object" } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm index 4ae636d4af05..ac674ca1c1a0 100644 --- a/maven-model/src/main/mdo/reader-ex.vm +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -19,6 +19,11 @@ #set ( $basePackage = "org.apache.maven.api.model" ) #set ( $package = "org.apache.maven.model.v4" ) #set ( $className = "MavenXpp3ReaderEx" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== @@ -589,15 +594,6 @@ public class ${className} * any. * @return Model */ -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end -#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) -#set ( $rootTag = $rootXml.tagName ) -#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) -#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) public Model read( XmlPullParser parser, boolean strict, InputSource source ) throws IOException, XmlPullParserException { diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm index 2c7604a192bc..725a43360f01 100644 --- a/maven-model/src/main/mdo/reader.vm +++ b/maven-model/src/main/mdo/reader.vm @@ -19,6 +19,11 @@ #set ( $basePackage = "org.apache.maven.api.model" ) #set ( $package = "org.apache.maven.model.v4" ) #set ( $className = "MavenXpp3Reader" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== @@ -620,15 +625,6 @@ public class ${className} * any. * @return Model */ -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end -#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) -#set ( $rootTag = $rootXml.tagName ) -#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) -#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) public Model read( XmlPullParser parser, boolean strict ) throws IOException, XmlPullParserException { diff --git a/maven-model/src/main/mdo/writer.vm b/maven-model/src/main/mdo/writer.vm index 7f126b0792a2..5ba0561da42b 100644 --- a/maven-model/src/main/mdo/writer.vm +++ b/maven-model/src/main/mdo/writer.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "org.apache.maven.api.model" ) #set ( $package = "org.apache.maven.model.v4" ) #set ( $className = "MavenXpp3Writer" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-plugin-api/src/main/mdo/merger.vm b/maven-plugin-api/src/main/mdo/merger.vm index 38c3614c489c..eb7070078fe8 100644 --- a/maven-plugin-api/src/main/mdo/merger.vm +++ b/maven-plugin-api/src/main/mdo/merger.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "${model.getDefault('package').getValue()}" ) #set ( $package = "${basePackage}.merge" ) #set ( $className = "${model.name}Merger" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-plugin-api/src/main/mdo/model.vm b/maven-plugin-api/src/main/mdo/model.vm index 01cb619fedd0..0bbda40c426a 100644 --- a/maven-plugin-api/src/main/mdo/model.vm +++ b/maven-plugin-api/src/main/mdo/model.vm @@ -17,6 +17,7 @@ under the License. *# #set ( $package = "${model.getDefault('package').getValue()}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -30,11 +31,6 @@ #end #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end - #end #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) diff --git a/maven-plugin-api/src/main/mdo/reader.vm b/maven-plugin-api/src/main/mdo/reader.vm index 68ef95cad8dd..dffe32d45bad 100644 --- a/maven-plugin-api/src/main/mdo/reader.vm +++ b/maven-plugin-api/src/main/mdo/reader.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "${model.getDefault('package').getValue()}" ) #set ( $package = "${basePackage}.io.xpp3" ) #set ( $className = "${model.name}Xpp3Reader" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-plugin-api/src/main/mdo/writer.vm b/maven-plugin-api/src/main/mdo/writer.vm index 80803fc61b47..ad63caa768b3 100644 --- a/maven-plugin-api/src/main/mdo/writer.vm +++ b/maven-plugin-api/src/main/mdo/writer.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "${model.getDefault('package').getValue()}" ) #set ( $package = "${basePackage}.io.xpp3" ) #set ( $className = "${model.name}Xpp3Writer" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-settings/src/main/mdo/merger.vm b/maven-settings/src/main/mdo/merger.vm index 10a66c17d84b..ce30e8cbe515 100644 --- a/maven-settings/src/main/mdo/merger.vm +++ b/maven-settings/src/main/mdo/merger.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "org.apache.maven.api.settings" ) #set ( $package = "org.apache.maven.settings.v4" ) #set ( $className = "${model.name}Merger" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-settings/src/main/mdo/model-v3.vm b/maven-settings/src/main/mdo/model-v3.vm index e4f84cd0d022..77f01221062c 100644 --- a/maven-settings/src/main/mdo/model-v3.vm +++ b/maven-settings/src/main/mdo/model-v3.vm @@ -19,6 +19,7 @@ #set ( $basePackage = "org.apache.maven.settings" ) #set ( $package = "${basePackage}" ) #set ( $wrapPackage = "org.apache.maven.api.settings" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -33,11 +34,6 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end - #end #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) diff --git a/maven-settings/src/main/mdo/reader.vm b/maven-settings/src/main/mdo/reader.vm index 533eaf84d2eb..946bc2d5c23b 100644 --- a/maven-settings/src/main/mdo/reader.vm +++ b/maven-settings/src/main/mdo/reader.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "org.apache.maven.api.settings" ) #set ( $package = "org.apache.maven.settings.v4" ) #set ( $className = "${model.name}Xpp3Reader" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-settings/src/main/mdo/writer.vm b/maven-settings/src/main/mdo/writer.vm index 5e3892c66986..a34ba83ecf1e 100644 --- a/maven-settings/src/main/mdo/writer.vm +++ b/maven-settings/src/main/mdo/writer.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "org.apache.maven.api.settings" ) #set ( $package = "org.apache.maven.settings.v4" ) #set ( $className = "${model.name}Xpp3Writer" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-toolchain-model/src/main/mdo/merger.vm b/maven-toolchain-model/src/main/mdo/merger.vm index 8deefff1c269..749725ffa1c3 100644 --- a/maven-toolchain-model/src/main/mdo/merger.vm +++ b/maven-toolchain-model/src/main/mdo/merger.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "org.apache.maven.api.toolchain" ) #set ( $package = "org.apache.maven.toolchain.v4" ) #set ( $className = "${model.name}Merger" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-toolchain-model/src/main/mdo/model-v3.vm b/maven-toolchain-model/src/main/mdo/model-v3.vm index 15bc43d9ce1f..11bb72f10fe7 100644 --- a/maven-toolchain-model/src/main/mdo/model-v3.vm +++ b/maven-toolchain-model/src/main/mdo/model-v3.vm @@ -19,6 +19,7 @@ #set ( $basePackage = "org.apache.maven.toolchain.model" ) #set ( $package = "${basePackage}" ) #set ( $wrapPackage = "org.apache.maven.api.toolchain" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -33,11 +34,6 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end - #end #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) diff --git a/maven-toolchain-model/src/main/mdo/reader.vm b/maven-toolchain-model/src/main/mdo/reader.vm index 2634e8b85056..df0c28237315 100644 --- a/maven-toolchain-model/src/main/mdo/reader.vm +++ b/maven-toolchain-model/src/main/mdo/reader.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "org.apache.maven.api.toolchain" ) #set ( $package = "org.apache.maven.toolchain.v4" ) #set ( $className = "${model.name}Xpp3Reader" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm index da5cce3e99f1..cc5588329521 100644 --- a/maven-toolchain-model/src/main/mdo/writer.vm +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -19,11 +19,7 @@ #set ( $basePackage = "org.apache.maven.api.toolchain" ) #set ( $package = "org.apache.maven.toolchain.v4" ) #set ( $className = "${model.name}Xpp3Writer" ) -#foreach ( $class in $model.allClasses ) - #if ( $class.getMetadata("org.codehaus.modello.plugin.model.ModelClassMetadata").rootElement ) - #set ( $root = $class ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) #set ( $rootUcapName = $Helper.capitalise( $root.name ) ) From 081e5ecbb2c1087d1893c220e2230853842cd1a3 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 13:59:45 +0200 Subject: [PATCH 32/98] Actually implement the extended writer, complete merger and transformer, reader cleanup --- .../model/io/xpp3/MavenXpp3WriterEx.java | 25 + maven-model/src/main/mdo/merger.vm | 10 + maven-model/src/main/mdo/reader-ex.vm | 1054 ++++++++--------- maven-model/src/main/mdo/reader.vm | 1021 ++++++++-------- maven-model/src/main/mdo/transformer.vm | 2 + maven-model/src/main/mdo/writer-ex.vm | 357 +++++- 6 files changed, 1407 insertions(+), 1062 deletions(-) diff --git a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java index f9ccb3b14190..ad6842564b2a 100644 --- a/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java +++ b/maven-model/src/main/java/org/apache/maven/model/io/xpp3/MavenXpp3WriterEx.java @@ -22,6 +22,8 @@ import java.io.IOException; import java.io.OutputStream; import java.io.Writer; + +import org.apache.maven.model.InputLocation; import org.apache.maven.model.Model; public class MavenXpp3WriterEx @@ -35,6 +37,11 @@ public class MavenXpp3WriterEx */ private String fileComment = null; + /** + * Field stringFormatter. + */ + protected InputLocation.StringFormatter stringFormatter; + //-----------/ //- Methods -/ @@ -50,6 +57,16 @@ public void setFileComment( String fileComment ) this.fileComment = fileComment; } //-- void setFileComment( String ) + /** + * Method setStringFormatter. + * + * @param stringFormatter + */ + public void setStringFormatter( InputLocation.StringFormatter stringFormatter ) + { + this.stringFormatter = stringFormatter; + } //-- void setStringFormatter( InputLocation.StringFormatter ) + /** * Method write. * @@ -62,6 +79,14 @@ public void write( Writer writer, Model model ) { org.apache.maven.model.v4.MavenXpp3WriterEx xw = new org.apache.maven.model.v4.MavenXpp3WriterEx(); xw.setFileComment( fileComment ); + xw.setStringFormatter( stringFormatter != null ? new org.apache.maven.api.model.InputLocation.StringFormatter() + { + @Override + public String toString( org.apache.maven.api.model.InputLocation location ) + { + return stringFormatter.toString( new InputLocation( location ) ); + } + } : null ); xw.write( writer, model.getDelegate() ); } //-- void write( Writer, Model ) diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm index 9b2bd0d06193..ffc06d2e9bcb 100644 --- a/maven-model/src/main/mdo/merger.vm +++ b/maven-model/src/main/mdo/merger.vm @@ -181,6 +181,16 @@ public class ${className} builder.configuration( tgt.merge( src ) ); } } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm index ac674ca1c1a0..726c60e1e2a8 100644 --- a/maven-model/src/main/mdo/reader-ex.vm +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -78,436 +78,337 @@ public class ${className} } /** - * Method checkFieldWithDuplicate. + * Returns the state of the "add default entities" flag. * - * @param parser a parser object. - * @param parsed a parsed object. - * @param alias a alias object. - * @param tagName a tagName object. - * @throws XmlPullParserException XmlPullParserException if - * any. * @return boolean */ - private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) - throws XmlPullParserException + public boolean getAddDefaultEntities() { - if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) - { - return false; - } - if ( !parsed.add( tagName ) ) - { - throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); - } - return true; - } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() /** - * Method checkUnknownAttribute. + * Sets the state of the "add default entities" flag. * - * @param parser a parser object. - * @param strict a strict object. - * @param tagName a tagName object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @throws IOException IOException if any. + * @param addDefaultEntities a addDefaultEntities object. */ - private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) - throws XmlPullParserException, IOException + public void setAddDefaultEntities( boolean addDefaultEntities ) { - // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too - if ( strict ) - { - throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); - } - } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) /** - * Method checkUnknownElement. + * @see ReaderFactory#newXmlReader * - * @param parser a parser object. + * @param reader a reader object. * @param strict a strict object. - * @throws XmlPullParserException XmlPullParserException if - * any. * @throws IOException IOException if any. - */ - private void checkUnknownElement( XmlPullParser parser, boolean strict ) - throws XmlPullParserException, IOException - { - if ( strict ) - { - throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); - } - - for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) - { - int eventType = parser.next(); - if ( eventType == XmlPullParser.START_TAG ) - { - unrecognizedTagCount++; - } - else if ( eventType == XmlPullParser.END_TAG ) - { - unrecognizedTagCount--; - } - } - } //-- void checkUnknownElement( XmlPullParser, boolean ) - - /** - * Returns the state of the "add default entities" flag. - * - * @return boolean - */ - public boolean getAddDefaultEntities() - { - return addDefaultEntities; - } //-- boolean getAddDefaultEntities() - - /** - * Method getBooleanValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return boolean + * @return Model */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException + public Model read( Reader reader, boolean strict, InputSource source ) + throws IOException, XmlPullParserException { - return getBooleanValue( s, attribute, parser, null ); - } //-- boolean getBooleanValue( String, String, XmlPullParser ) + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); + parser.setInput( reader ); + return read( parser, strict, source ); + } //-- Model read( Reader, boolean ) /** - * Method getBooleanValue. + * Method read. * - * @param s a s object. - * @param defaultValue a defaultValue object. - * @param parser a parser object. - * @param attribute a attribute object. + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return boolean + * @return Model */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) - throws XmlPullParserException + public Model read( InputStream in, boolean strict, InputSource source ) + throws IOException, XmlPullParserException { - if ( s != null && s.length() != 0 ) - { - return Boolean.valueOf( s ).booleanValue(); - } - if ( defaultValue != null ) - { - return Boolean.valueOf( defaultValue ).booleanValue(); - } - return false; - } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + return read( ReaderFactory.newXmlReader( in ), strict, source ); + } //-- Model read( InputStream, boolean ) /** - * Method getByteValue. + * Method read. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. - * @param attribute a attribute object. + * @param strict a strict object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return byte + * @return Model */ - private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + public Model read( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException { - if ( s != null ) + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) { - try - { - return Byte.valueOf( s ).byteValue(); - } - catch ( NumberFormatException nfe ) + if ( eventType == XmlPullParser.START_TAG ) { - if ( strict ) + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); } + $rootLcapName = parse${rootUcapName}( parser, strict, source ); + parsed = true; } + eventType = parser.next(); } - return 0; - } //-- byte getByteValue( String, String, XmlPullParser, boolean ) - - /** - * Method getCharacterValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return char - */ - private char getCharacterValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - if ( s != null ) + if ( parsed ) { - return s.charAt( 0 ); + return $rootLcapName; } - return 0; - } //-- char getCharacterValue( String, String, XmlPullParser ) - - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - return getDateValue( s, attribute, null, parser ); - } //-- Date getDateValue( String, String, XmlPullParser ) + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- Model read( XmlPullParser, boolean ) - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param dateFormat a dateFormat object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) - throws XmlPullParserException +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict, InputSource source ) + throws IOException, XmlPullParserException { - if ( s != null ) + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + ${classLcapName}.location( "", new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) { - String effectiveDateFormat = dateFormat; - if ( dateFormat == null ) + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) { - effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + // just ignore attributes with non-default namespace (for example: xmlns:xsi) } - if ( "long".equals( effectiveDateFormat ) ) + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) { - try - { - return new java.util.Date( Long.parseLong( s ) ); - } - catch ( NumberFormatException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } + // ignore xmlns attribute in root class, which is a reserved attribute name } - else + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) { - try - { - DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); - return dateParser.parse( s ); - } - catch ( java.text.ParseException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } + ${classLcapName}.location( name, new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); } } - return null; - } //-- Date getDateValue( String, String, String, XmlPullParser ) - - /** - * Method getDoubleValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return double - */ - private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) + Set parsed = new HashSet<>(); + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) { - try + String childName = unalias( parser.getName() ); + if ( !parsed.add( childName ) ) { - return Double.valueOf( s ).doubleValue(); + throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); } - catch ( NumberFormatException nfe ) + int line = parser.getLineNumber(); + int column = parser.getColumnNumber(); + Map locations = null; + switch ( childName ) { - if ( strict ) + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + locations = new HashMap<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + locations.put( Integer.valueOf( locations.size() ), new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + locations = new HashMap<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + locations.put( key, new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict, source ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict, source ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; } } + ${classLcapName}.location( childName, new InputLocation( line, column, source, locations ) ); } - return 0; - } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + return ${classLcapName}.build(); + } - /** - * Method getFloatValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return float - */ - private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + #end +#end + + private String unalias( String tagName ) { - if ( s != null ) + switch ( tagName ) { - try - { - return Float.valueOf( s ).floatValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); - } - } +#set( $aliases = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.allFields ) + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) + #end + #end +#end +#foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + return "${entry.value}"; +#end + default: + return tagName; } - return 0; - } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + } /** - * Method getIntegerValue. + * Method checkUnknownAttribute. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return int + * @throws IOException IOException if any. */ - private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException { - if ( s != null ) + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) { - try - { - return Integer.valueOf( s ).intValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); - } - } + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); } - return 0; - } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) /** - * Method getLongValue. + * Method checkUnknownElement. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. - * @param attribute a attribute object. + * @param strict a strict object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return long + * @throws IOException IOException if any. */ - private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException { - if ( s != null ) + if ( strict ) { - try + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) { - return Long.valueOf( s ).longValue(); + unrecognizedTagCount++; } - catch ( NumberFormatException nfe ) + else if ( eventType == XmlPullParser.END_TAG ) { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); - } + unrecognizedTagCount--; } } - return 0; - } //-- long getLongValue( String, String, XmlPullParser, boolean ) + } //-- void checkUnknownElement( XmlPullParser, boolean ) /** - * Method getRequiredAttributeValue. + * Method getTrimmedValue. * * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. * @return String */ - private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + private String getTrimmedValue( String s ) { - if ( s == null ) - { - if ( strict ) - { - throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); - } - } - return s; - } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) - - /** - * Method getShortValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return short - */ - private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Short.valueOf( s ).shortValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); - } - } - } - return 0; - } //-- short getShortValue( String, String, XmlPullParser, boolean ) - - /** - * Method getTrimmedValue. - * - * @param s a s object. - * @return String - */ - private String getTrimmedValue( String s ) - { - if ( s != null ) + if ( s != null ) { s = s.trim(); } @@ -551,265 +452,342 @@ public class ${className} } //-- int nextTag( XmlPullParser ) /** - * @see ReaderFactory#newXmlReader + * Method getBooleanValue. * - * @param reader a reader object. - * @param strict a strict object. - * @throws IOException IOException if any. + * @param s a s object. + * @param defaultValue a defaultValue object. + * @param parser a parser object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return boolean */ - public Model read( Reader reader, boolean strict, InputSource source ) - throws IOException, XmlPullParserException + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + throws XmlPullParserException { - XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); - parser.setInput( reader ); - return read( parser, strict, source ); - } //-- Model read( Reader, boolean ) + if ( s != null && s.length() != 0 ) + { + return Boolean.valueOf( s ).booleanValue(); + } + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) +#if ( "0" == "1" ) /** - * Method read. + * Method getBooleanValue. * - * @param in a in object. - * @param strict a strict object. - * @throws IOException IOException if any. + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return boolean */ - public Model read( InputStream in, boolean strict, InputSource source ) - throws IOException, XmlPullParserException + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException { - return read( ReaderFactory.newXmlReader( in ), strict, source ); - } //-- Model read( InputStream, boolean ) + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) /** - * Method read. + * Method getByteValue. * - * @param parser a parser object. + * @param s a s object. * @param strict a strict object. - * @throws IOException IOException if any. + * @param parser a parser object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return byte */ - public Model read( XmlPullParser parser, boolean strict, InputSource source ) - throws IOException, XmlPullParserException + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException { - $rootUcapName $rootLcapName = null; - int eventType = parser.getEventType(); - boolean parsed = false; - while ( eventType != XmlPullParser.END_DOCUMENT ) + if ( s != null ) { - if ( eventType == XmlPullParser.START_TAG ) + try { - if ( strict && ! "${rootTag}".equals( parser.getName() ) ) - { - throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); - } - else if ( parsed ) + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) { - // fallback, already expected a XmlPullParserException due to invalid XML - throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); } - $rootLcapName = parse${rootUcapName}( parser, strict, source ); - parsed = true; } - eventType = parser.next(); } - if ( parsed ) + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) + + /** + * Method getCharacterValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return char + */ + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) { - return $rootLcapName; + return s.charAt( 0 ); } - throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); - } //-- Model read( XmlPullParser, boolean ) + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) -#foreach ( $class in $model.allClasses ) - #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) - #set ( $classUcapName = $Helper.capitalise( $class.name ) ) - #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) - #set ( $ancestors = $Helper.ancestors( $class ) ) - #set ( $allFields = [] ) - #foreach ( $cl in $ancestors ) - #set ( $dummy = $allFields.addAll( $cl.allFields ) ) - #end - private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict, InputSource source ) - throws IOException, XmlPullParserException + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException { - String tagName = parser.getName(); - ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); - ${classLcapName}.location( "", new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); - for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) + + /** + * Method getDateValue. + * + * @param s a s object. + * @param parser a parser object. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Date + */ + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException + { + if ( s != null ) { - String name = parser.getAttributeName( i ); - String value = parser.getAttributeValue( i ); - if ( name.indexOf( ':' ) >= 0 ) - { - // just ignore attributes with non-default namespace (for example: xmlns:xsi) - } - #if ( $class == $root ) - else if ( "xmlns".equals( name ) ) + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) { - // ignore xmlns attribute in root class, which is a reserved attribute name + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; } - #end - #foreach ( $field in $allFields ) - #if ( $Helper.xmlFieldMetadata( $field ).attribute ) - #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) - #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) - else if ( "$fieldTagName".equals( name ) ) + if ( "long".equals( effectiveDateFormat ) ) { - #if ( $field.type == "String" ) - ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); - #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); - #else - // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} - #end + try + { + return new java.util.Date( Long.parseLong( s ) ); + } + catch ( NumberFormatException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } } - #end - #end else { - checkUnknownAttribute( parser, name, tagName, strict ); + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); + } } } - Set parsed = new HashSet<>(); - while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) - { - String childName = unalias( parser.getName() ); - if ( !parsed.add( childName ) ) - { - throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); - } - int line = parser.getLineNumber(); - int column = parser.getColumnNumber(); - Map locations = null; - switch ( childName ) + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) + + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try { - #set( $ift = "if" ) - #foreach ( $field in $allFields ) - #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) - #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) - #if ( ! $fieldTagName ) - #set ( $fieldTagName = $field.name ) - #end - #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) - case "${fieldTagName}": + return Double.valueOf( s ).doubleValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) { - #if ( $field.type == "String" ) - ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); - break; - #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); - break; - #elseif ( $field.type == "int" ) - ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); - break; - #elseif ( $field.type == "DOM" ) - ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); - break; - #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) - List ${field.name} = new ArrayList<>(); - locations = new HashMap<>(); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) - { - locations.put( Integer.valueOf( locations.size() ), new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); - ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); - } - else - { - checkUnknownElement( parser, strict ); - } - } - ${classLcapName}.${field.name}( ${field.name} ); - break; - #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) - Properties ${field.name} = new Properties(); - // TODO: locations - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - String key = parser.getName(); - String value = parser.nextText().trim(); - ${field.name}.put( key, value ); - } - ${classLcapName}.${field.name}( ${field.name} ); - break; - #elseif ( $field.to && $field.multiplicity == "1" ) - ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict, source ) ); - break; - #elseif ( $field.to && $field.multiplicity == "*" ) - List<$field.to> ${field.name} = new ArrayList<>(); - locations = new HashMap<>(); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) - { - locations.put( Integer.valueOf( locations.size() ), new InputLocation( parser.getLineNumber(), parser.getColumnNumber(), source ) ); - ${field.name}.add( parse${field.toClass.name}( parser, strict, source ) ); - } - else - { - checkUnknownElement( parser, strict ); - } - } - ${classLcapName}.${field.name}( ${field.name} ); - break; - #else - // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} - break; - #end + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); } - #set( $ift = "else if" ) - #end - #end - default: + } + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Float.valueOf( s ).floatValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) { - checkUnknownElement( parser, strict ); - break; + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); } } - ${classLcapName}.location( childName, new InputLocation( line, column, source, locations ) ); } - return ${classLcapName}.build(); - } + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) - #end -#end + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Integer.valueOf( s ).intValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); + } + } + } + return 0; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) - private String unalias( String tagName ) + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException { - switch ( tagName ) + if ( s != null ) { -#set( $aliases = { } ) -#foreach( $class in $model.allClasses ) - #foreach ( $field in $class.allFields ) - #if ( $field.alias ) - #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) - #end - #end -#end -#foreach( $entry in $aliases.entrySet() ) - case "${entry.key}": - return "${entry.value}"; -#end - default: - return tagName; + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); + } + } } - } + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) /** - * Sets the state of the "add default entities" flag. + * Method getRequiredAttributeValue. * - * @param addDefaultEntities a addDefaultEntities object. + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String */ - public void setAddDefaultEntities( boolean addDefaultEntities ) + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException { - this.addDefaultEntities = addDefaultEntities; - } //-- void setAddDefaultEntities( boolean ) + if ( s == null ) + { + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } + } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) + + /** + * Method getShortValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short + */ + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) + +#end public static interface ContentTransformer { diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm index 725a43360f01..c5cee0d6c2c9 100644 --- a/maven-model/src/main/mdo/reader.vm +++ b/maven-model/src/main/mdo/reader.vm @@ -76,429 +76,378 @@ public class ${className} } /** - * Method checkFieldWithDuplicate. + * Returns the state of the "add default entities" flag. * - * @param parser a parser object. - * @param parsed a parsed object. - * @param alias a alias object. - * @param tagName a tagName object. - * @throws XmlPullParserException XmlPullParserException if - * any. * @return boolean */ - private boolean checkFieldWithDuplicate( XmlPullParser parser, String tagName, String alias, Set parsed ) - throws XmlPullParserException + public boolean getAddDefaultEntities() { - if ( !( parser.getName().equals( tagName ) || parser.getName().equals( alias ) ) ) - { - return false; - } - if ( !parsed.add( tagName ) ) - { - throw new XmlPullParserException( "Duplicated tag: '" + tagName + "'", parser, null ); - } - return true; - } //-- boolean checkFieldWithDuplicate( XmlPullParser, String, String, Set ) + return addDefaultEntities; + } //-- boolean getAddDefaultEntities() /** - * Method checkUnknownAttribute. + * Sets the state of the "add default entities" flag. * - * @param parser a parser object. - * @param strict a strict object. - * @param tagName a tagName object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @throws IOException IOException if any. + * @param addDefaultEntities a addDefaultEntities object. */ - private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) - throws XmlPullParserException, IOException + public void setAddDefaultEntities( boolean addDefaultEntities ) { - // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too - if ( strict ) - { - throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); - } - } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) + this.addDefaultEntities = addDefaultEntities; + } //-- void setAddDefaultEntities( boolean ) /** - * Method checkUnknownElement. + * @see ReaderFactory#newXmlReader * - * @param parser a parser object. + * @param reader a reader object. * @param strict a strict object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @throws IOException IOException if any. + * @return Model */ - private void checkUnknownElement( XmlPullParser parser, boolean strict ) - throws XmlPullParserException, IOException + public Model read( Reader reader, boolean strict ) + throws IOException, XmlPullParserException { - if ( strict ) - { - throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); - } + XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); - for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) - { - int eventType = parser.next(); - if ( eventType == XmlPullParser.START_TAG ) - { - unrecognizedTagCount++; - } - else if ( eventType == XmlPullParser.END_TAG ) - { - unrecognizedTagCount--; - } - } - } //-- void checkUnknownElement( XmlPullParser, boolean ) + parser.setInput( reader ); + + + return read( parser, strict ); + } //-- Model read( Reader, boolean ) /** - * Returns the state of the "add default entities" flag. + * @see ReaderFactory#newXmlReader * - * @return boolean + * @param reader a reader object. + * @throws IOException IOException if any. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return Model */ - public boolean getAddDefaultEntities() + public Model read( Reader reader ) + throws IOException, XmlPullParserException { - return addDefaultEntities; - } //-- boolean getAddDefaultEntities() + return read( reader, true ); + } //-- Model read( Reader ) /** - * Method getBooleanValue. + * Method read. * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. + * @param in a in object. + * @param strict a strict object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return boolean + * @return Model */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException + public Model read( InputStream in, boolean strict ) + throws IOException, XmlPullParserException { - return getBooleanValue( s, attribute, parser, null ); - } //-- boolean getBooleanValue( String, String, XmlPullParser ) + return read( ReaderFactory.newXmlReader( in ), strict ); + } //-- Model read( InputStream, boolean ) /** - * Method getBooleanValue. + * Method read. * - * @param s a s object. - * @param defaultValue a defaultValue object. - * @param parser a parser object. - * @param attribute a attribute object. + * @param in a in object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return boolean + * @return Model */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) - throws XmlPullParserException + public Model read( InputStream in ) + throws IOException, XmlPullParserException { - if ( s != null && s.length() != 0 ) - { - return Boolean.valueOf( s ).booleanValue(); - } - if ( defaultValue != null ) - { - return Boolean.valueOf( defaultValue ).booleanValue(); - } - return false; - } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) + return read( ReaderFactory.newXmlReader( in ) ); + } //-- Model read( InputStream ) /** - * Method getByteValue. + * Method read. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. - * @param attribute a attribute object. + * @param strict a strict object. + * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return byte + * @return Model */ - private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + public Model read( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException { - if ( s != null ) + $rootUcapName $rootLcapName = null; + int eventType = parser.getEventType(); + boolean parsed = false; + while ( eventType != XmlPullParser.END_DOCUMENT ) { - try - { - return Byte.valueOf( s ).byteValue(); - } - catch ( NumberFormatException nfe ) + if ( eventType == XmlPullParser.START_TAG ) { - if ( strict ) + if ( strict && ! "${rootTag}".equals( parser.getName() ) ) { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + } + else if ( parsed ) + { + // fallback, already expected a XmlPullParserException due to invalid XML + throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); } + $rootLcapName = parse${rootUcapName}( parser, strict ); + parsed = true; } + eventType = parser.next(); } - return 0; - } //-- byte getByteValue( String, String, XmlPullParser, boolean ) - - /** - * Method getCharacterValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return char - */ - private char getCharacterValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - if ( s != null ) + if ( parsed ) { - return s.charAt( 0 ); + return $rootLcapName; } - return 0; - } //-- char getCharacterValue( String, String, XmlPullParser ) - - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - return getDateValue( s, attribute, null, parser ); - } //-- Date getDateValue( String, String, XmlPullParser ) + throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); + } //-- Model read( XmlPullParser, boolean ) - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param dateFormat a dateFormat object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) - throws XmlPullParserException +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $ancestors = $Helper.ancestors( $class ) ) + #set ( $allFields = [] ) + #foreach ( $cl in $ancestors ) + #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #end + private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) + throws IOException, XmlPullParserException { - if ( s != null ) + String tagName = parser.getName(); + ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); + for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) { - String effectiveDateFormat = dateFormat; - if ( dateFormat == null ) + String name = parser.getAttributeName( i ); + String value = parser.getAttributeValue( i ); + if ( name.indexOf( ':' ) >= 0 ) { - effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + // just ignore attributes with non-default namespace (for example: xmlns:xsi) } - if ( "long".equals( effectiveDateFormat ) ) + #if ( $class == $root ) + else if ( "xmlns".equals( name ) ) { - try - { - return new java.util.Date( Long.parseLong( s ) ); - } - catch ( NumberFormatException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } + // ignore xmlns attribute in root class, which is a reserved attribute name } - else - { - try - { - DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); - return dateParser.parse( s ); - } - catch ( java.text.ParseException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + else if ( "$fieldTagName".equals( name ) ) + { + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + } + #end + #end + else + { + checkUnknownAttribute( parser, name, tagName, strict ); } } - return null; - } //-- Date getDateValue( String, String, String, XmlPullParser ) - - /** - * Method getDoubleValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return double - */ - private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) + Set parsed = new HashSet<>(); + while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) { - try + String childName = unalias( parser.getName() ); + if ( !parsed.add( childName ) ) { - return Double.valueOf( s ).doubleValue(); + throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); } - catch ( NumberFormatException nfe ) + switch ( childName ) { - if ( strict ) + #set( $ift = "if" ) + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + case "${fieldTagName}": { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + #if ( $field.type == "String" ) + ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + break; + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "int" ) + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + break; + #elseif ( $field.type == "DOM" ) + ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); + break; + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + List ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + Properties ${field.name} = new Properties(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + String key = parser.getName(); + String value = parser.nextText().trim(); + ${field.name}.put( key, value ); + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #elseif ( $field.to && $field.multiplicity == "1" ) + ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); + break; + #elseif ( $field.to && $field.multiplicity == "*" ) + List<$field.to> ${field.name} = new ArrayList<>(); + while ( parser.nextTag() == XmlPullParser.START_TAG ) + { + if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) + { + ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); + } + else + { + checkUnknownElement( parser, strict ); + } + } + ${classLcapName}.${field.name}( ${field.name} ); + break; + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + break; + #end + } + #set( $ift = "else if" ) + #end + #end + default: + { + checkUnknownElement( parser, strict ); + break; } } } - return 0; - } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + return ${classLcapName}.build(); + } + + #end +#end + + private String unalias( String tagName ) + { + switch ( tagName ) + { +#set( $aliases = { } ) +#foreach( $class in $model.allClasses ) + #foreach ( $field in $class.allFields ) + #if ( $field.alias ) + #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) + #end + #end +#end +#foreach( $entry in $aliases.entrySet() ) + case "${entry.key}": + return "${entry.value}"; +#end + default: + return tagName; + } + } /** - * Method getFloatValue. + * Method checkUnknownAttribute. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. + * @param strict a strict object. + * @param tagName a tagName object. * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return float + * @throws IOException IOException if any. */ - private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + private void checkUnknownAttribute( XmlPullParser parser, String attribute, String tagName, boolean strict ) + throws XmlPullParserException, IOException { - if ( s != null ) + // strictXmlAttributes = true for model: if strict == true, not only elements are checked but attributes too + if ( strict ) { - try - { - return Float.valueOf( s ).floatValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); - } - } + throw new XmlPullParserException( "Unknown attribute '" + attribute + "' for tag '" + tagName + "'", parser, null ); } - return 0; - } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + } //-- void checkUnknownAttribute( XmlPullParser, String, String, boolean ) /** - * Method getIntegerValue. + * Method checkUnknownElement. * - * @param s a s object. - * @param strict a strict object. * @param parser a parser object. - * @param attribute a attribute object. + * @param strict a strict object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return int + * @throws IOException IOException if any. */ - private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException + private void checkUnknownElement( XmlPullParser parser, boolean strict ) + throws XmlPullParserException, IOException { - if ( s != null ) + if ( strict ) { - try + throw new XmlPullParserException( "Unrecognised tag: '" + parser.getName() + "'", parser, null ); + } + + for ( int unrecognizedTagCount = 1; unrecognizedTagCount > 0; ) + { + int eventType = parser.next(); + if ( eventType == XmlPullParser.START_TAG ) { - return Integer.valueOf( s ).intValue(); + unrecognizedTagCount++; } - catch ( NumberFormatException nfe ) + else if ( eventType == XmlPullParser.END_TAG ) { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); - } + unrecognizedTagCount--; } } - return 0; - } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) + } //-- void checkUnknownElement( XmlPullParser, boolean ) /** - * Method getLongValue. + * Method getBooleanValue. * * @param s a s object. - * @param strict a strict object. + * @param defaultValue a defaultValue object. * @param parser a parser object. * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return long + * @return boolean */ - private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) throws XmlPullParserException { - if ( s != null ) + if ( s != null && s.length() != 0 ) { - try - { - return Long.valueOf( s ).longValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); - } - } + return Boolean.valueOf( s ).booleanValue(); } - return 0; - } //-- long getLongValue( String, String, XmlPullParser, boolean ) + if ( defaultValue != null ) + { + return Boolean.valueOf( defaultValue ).booleanValue(); + } + return false; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) /** - * Method getRequiredAttributeValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return String - */ - private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s == null ) - { - if ( strict ) - { - throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); - } - } - return s; - } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) - - /** - * Method getShortValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return short - */ - private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Short.valueOf( s ).shortValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); - } - } - } - return 0; - } //-- short getShortValue( String, String, XmlPullParser, boolean ) - - /** - * Method getTrimmedValue. + * Method getTrimmedValue. * * @param s a s object. * @return String @@ -548,290 +497,318 @@ public class ${className} return eventType; } //-- int nextTag( XmlPullParser ) +#if ( "0" == "1" ) /** - * @see ReaderFactory#newXmlReader + * Method getBooleanValue. * - * @param reader a reader object. - * @param strict a strict object. - * @throws IOException IOException if any. + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return boolean */ - public Model read( Reader reader, boolean strict ) - throws IOException, XmlPullParserException + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException { - XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); - - parser.setInput( reader ); - - - return read( parser, strict ); - } //-- Model read( Reader, boolean ) + return getBooleanValue( s, attribute, parser, null ); + } //-- boolean getBooleanValue( String, String, XmlPullParser ) /** - * @see ReaderFactory#newXmlReader + * Method getByteValue. * - * @param reader a reader object. - * @throws IOException IOException if any. + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return byte */ - public Model read( Reader reader ) - throws IOException, XmlPullParserException + private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException { - return read( reader, true ); - } //-- Model read( Reader ) + if ( s != null ) + { + try + { + return Byte.valueOf( s ).byteValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); + } + } + } + return 0; + } //-- byte getByteValue( String, String, XmlPullParser, boolean ) /** - * Method read. + * Method getCharacterValue. * - * @param in a in object. - * @param strict a strict object. - * @throws IOException IOException if any. + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return char */ - public Model read( InputStream in, boolean strict ) - throws IOException, XmlPullParserException + private char getCharacterValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException { - return read( ReaderFactory.newXmlReader( in ), strict ); - } //-- Model read( InputStream, boolean ) + if ( s != null ) + { + return s.charAt( 0 ); + } + return 0; + } //-- char getCharacterValue( String, String, XmlPullParser ) /** - * Method read. + * Method getDateValue. * - * @param in a in object. - * @throws IOException IOException if any. + * @param s a s object. + * @param parser a parser object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return Date */ - public Model read( InputStream in ) - throws IOException, XmlPullParserException + private Date getDateValue( String s, String attribute, XmlPullParser parser ) + throws XmlPullParserException { - return read( ReaderFactory.newXmlReader( in ) ); - } //-- Model read( InputStream ) + return getDateValue( s, attribute, null, parser ); + } //-- Date getDateValue( String, String, XmlPullParser ) /** - * Method read. + * Method getDateValue. * + * @param s a s object. * @param parser a parser object. - * @param strict a strict object. - * @throws IOException IOException if any. + * @param dateFormat a dateFormat object. + * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return Date */ - public Model read( XmlPullParser parser, boolean strict ) - throws IOException, XmlPullParserException + private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) + throws XmlPullParserException { - $rootUcapName $rootLcapName = null; - int eventType = parser.getEventType(); - boolean parsed = false; - while ( eventType != XmlPullParser.END_DOCUMENT ) + if ( s != null ) { - if ( eventType == XmlPullParser.START_TAG ) + String effectiveDateFormat = dateFormat; + if ( dateFormat == null ) { - if ( strict && ! "${rootTag}".equals( parser.getName() ) ) + effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; + } + if ( "long".equals( effectiveDateFormat ) ) + { + try { - throw new XmlPullParserException( "Expected root element '${rootTag}' but found '" + parser.getName() + "'", parser, null ); + return new java.util.Date( Long.parseLong( s ) ); } - else if ( parsed ) + catch ( NumberFormatException e ) { - // fallback, already expected a XmlPullParserException due to invalid XML - throw new XmlPullParserException( "Duplicated tag: '${rootTag}'", parser, null ); + throw new XmlPullParserException( e.getMessage(), parser, e ); + } + } + else + { + try + { + DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); + return dateParser.parse( s ); + } + catch ( java.text.ParseException e ) + { + throw new XmlPullParserException( e.getMessage(), parser, e ); } - $rootLcapName = parse${rootUcapName}( parser, strict ); - parsed = true; } - eventType = parser.next(); - } - if ( parsed ) - { - return $rootLcapName; } - throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); - } //-- Model read( XmlPullParser, boolean ) + return null; + } //-- Date getDateValue( String, String, String, XmlPullParser ) -#foreach ( $class in $model.allClasses ) - #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) - #set ( $classUcapName = $Helper.capitalise( $class.name ) ) - #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) - #set ( $ancestors = $Helper.ancestors( $class ) ) - #set ( $allFields = [] ) - #foreach ( $cl in $ancestors ) - #set ( $dummy = $allFields.addAll( $cl.allFields ) ) - #end - private ${classUcapName} parse${classUcapName}( XmlPullParser parser, boolean strict ) - throws IOException, XmlPullParserException + /** + * Method getDoubleValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return double + */ + private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException { - String tagName = parser.getName(); - ${classUcapName}.Builder ${classLcapName} = ${classUcapName}.newBuilder( true ); - for ( int i = parser.getAttributeCount() - 1; i >= 0; i-- ) + if ( s != null ) { - String name = parser.getAttributeName( i ); - String value = parser.getAttributeValue( i ); - if ( name.indexOf( ':' ) >= 0 ) + try { - // just ignore attributes with non-default namespace (for example: xmlns:xsi) + return Double.valueOf( s ).doubleValue(); } - #if ( $class == $root ) - else if ( "xmlns".equals( name ) ) + catch ( NumberFormatException nfe ) { - // ignore xmlns attribute in root class, which is a reserved attribute name + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } } - #end - #foreach ( $field in $allFields ) - #if ( $Helper.xmlFieldMetadata( $field ).attribute ) - #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) - #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) - else if ( "$fieldTagName".equals( name ) ) + } + return 0; + } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) + + /** + * Method getFloatValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return float + */ + private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try { - #if ( $field.type == "String" ) - ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); - #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); - #else - // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} - #end + return Float.valueOf( s ).floatValue(); } - #end - #end - else + catch ( NumberFormatException nfe ) { - checkUnknownAttribute( parser, name, tagName, strict ); + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); + } } } - Set parsed = new HashSet<>(); - while ( ( strict ? parser.nextTag() : nextTag( parser ) ) == XmlPullParser.START_TAG ) + return 0; + } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + + /** + * Method getIntegerValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return int + */ + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) { - String childName = unalias( parser.getName() ); - if ( !parsed.add( childName ) ) + try { - throw new XmlPullParserException( "Duplicated tag: '" + childName + "'", parser, null ); + return Integer.valueOf( s ).intValue(); } - switch ( childName ) + catch ( NumberFormatException nfe ) { - #set( $ift = "if" ) - #foreach ( $field in $allFields ) - #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) - #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) - #if ( ! $fieldTagName ) - #set ( $fieldTagName = $field.name ) - #end - #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) - case "${fieldTagName}": + if ( strict ) { - #if ( $field.type == "String" ) - ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); - break; - #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); - break; - #elseif ( $field.type == "int" ) - ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); - break; - #elseif ( $field.type == "DOM" ) - ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); - break; - #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) - List ${field.name} = new ArrayList<>(); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) - { - ${field.name}.add( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); - } - else - { - checkUnknownElement( parser, strict ); - } - } - ${classLcapName}.${field.name}( ${field.name} ); - break; - #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) - Properties ${field.name} = new Properties(); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - String key = parser.getName(); - String value = parser.nextText().trim(); - ${field.name}.put( key, value ); - } - ${classLcapName}.${field.name}( ${field.name} ); - break; - #elseif ( $field.to && $field.multiplicity == "1" ) - ${classLcapName}.${field.name}( parse${field.toClass.name}( parser, strict ) ); - break; - #elseif ( $field.to && $field.multiplicity == "*" ) - List<$field.to> ${field.name} = new ArrayList<>(); - while ( parser.nextTag() == XmlPullParser.START_TAG ) - { - if ( "${Helper.singular($fieldTagName)}".equals( parser.getName() ) ) - { - ${field.name}.add( parse${field.toClass.name}( parser, strict ) ); - } - else - { - checkUnknownElement( parser, strict ); - } - } - ${classLcapName}.${field.name}( ${field.name} ); - break; - #else - // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} - break; - #end + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be an integer", parser, nfe ); } - #set( $ift = "else if" ) - #end - #end - default: + } + } + return 0; + } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) + + /** + * Method getLongValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return long + */ + private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException + { + if ( s != null ) + { + try + { + return Long.valueOf( s ).longValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) { - checkUnknownElement( parser, strict ); - break; + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); } } } - return ${classLcapName}.build(); - } - - #end -#end + return 0; + } //-- long getLongValue( String, String, XmlPullParser, boolean ) - private String unalias( String tagName ) + /** + * Method getRequiredAttributeValue. + * + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return String + */ + private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException { - switch ( tagName ) + if ( s == null ) { -#set( $aliases = { } ) -#foreach( $class in $model.allClasses ) - #foreach ( $field in $class.allFields ) - #if ( $field.alias ) - #set ( $dummy = $aliases.put( $field.alias, $field.name ) ) - #end - #end -#end -#foreach( $entry in $aliases.entrySet() ) - case "${entry.key}": - return "${entry.value}"; -#end - default: - return tagName; + if ( strict ) + { + throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); + } } - } + return s; + } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) /** - * Sets the state of the "add default entities" flag. + * Method getShortValue. * - * @param addDefaultEntities a addDefaultEntities object. + * @param s a s object. + * @param strict a strict object. + * @param parser a parser object. + * @param attribute a attribute object. + * @throws XmlPullParserException XmlPullParserException if + * any. + * @return short */ - public void setAddDefaultEntities( boolean addDefaultEntities ) + private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) + throws XmlPullParserException { - this.addDefaultEntities = addDefaultEntities; - } //-- void setAddDefaultEntities( boolean ) + if ( s != null ) + { + try + { + return Short.valueOf( s ).shortValue(); + } + catch ( NumberFormatException nfe ) + { + if ( strict ) + { + throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); + } + } + } + return 0; + } //-- short getShortValue( String, String, XmlPullParser, boolean ) +#end public static interface ContentTransformer { /** diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm index f046c1640851..fb2817ca7338 100644 --- a/maven-model/src/main/mdo/transformer.vm +++ b/maven-model/src/main/mdo/transformer.vm @@ -133,6 +133,8 @@ public class ${className} #elseif ( $field.type == "DOM" ) Dom newVal = transform( target.get${capField}() ); builder.${field.name}( newVal != target.get${capField}() ? newVal : null ); + #elseif ( $field.type == "boolean" || $field.type == "int" || $field.type == "java.nio.file.Path" ) + // nothing to do, the transformer only handles strings #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end diff --git a/maven-model/src/main/mdo/writer-ex.vm b/maven-model/src/main/mdo/writer-ex.vm index 5a98d8a5664e..737ec8e32fab 100644 --- a/maven-model/src/main/mdo/writer-ex.vm +++ b/maven-model/src/main/mdo/writer-ex.vm @@ -19,6 +19,11 @@ #set ( $basePackage = "org.apache.maven.api.model" ) #set ( $package = "org.apache.maven.model.v4" ) #set ( $className = "MavenXpp3WriterEx" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) +#set ( $rootTag = $rootXml.tagName ) +#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) +#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== @@ -26,10 +31,358 @@ // ============================================================== package ${package}; +import java.io.IOException; +import java.io.InputStream; +import java.io.OutputStream; +import java.io.Reader; +import java.io.Writer; +import java.text.DateFormat; +import java.util.ArrayList; +import java.util.Date; +import java.util.HashSet; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Properties; +import java.util.Set; import org.apache.maven.api.annotations.Generated; +import org.apache.maven.api.model.InputLocationTracker; +import org.apache.maven.api.xml.Dom; +import org.apache.maven.internal.xml.DomBuilder; +#foreach ( $class in $model.allClasses ) +import ${basePackage}.${class.name}; +#end +import org.codehaus.plexus.util.ReaderFactory; +import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; +import org.codehaus.plexus.util.xml.pull.MXParser; +import org.codehaus.plexus.util.xml.pull.MXSerializer; +import org.codehaus.plexus.util.xml.pull.XmlPullParser; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.codehaus.plexus.util.xml.pull.XmlSerializer; @Generated -public class ${className} extends MavenXpp3Writer +public class ${className} { - // TODO: handle locations + //--------------------------/ + //- Class/Member Variables -/ + //--------------------------/ + + /** + * Field NAMESPACE. + */ + private static final String NAMESPACE = null; + + /** + * Field fileComment. + */ + private String fileComment = null; + + /** + * Field stringFormatter. + */ + protected InputLocation.StringFormatter stringFormatter; + + //-----------/ + //- Methods -/ + //-----------/ + + /** + * Method setFileComment. + * + * @param fileComment a fileComment object. + */ + public void setFileComment( String fileComment ) + { + this.fileComment = fileComment; + } //-- void setFileComment( String ) + + /** + * Method setStringFormatter. + * + * @param stringFormatter + */ + public void setStringFormatter( InputLocation.StringFormatter stringFormatter ) + { + this.stringFormatter = stringFormatter; + } //-- void setStringFormatter( InputLocation.StringFormatter ) + + /** + * Method write. + * + * @param writer a writer object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( Writer writer, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( writer ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( Writer, ${root.name} ) + + /** + * Method write. + * + * @param stream a stream object. + * @param model a model object. + * @throws java.io.IOException java.io.IOException if any. + */ + public void write( OutputStream stream, ${root.name} ${rootLcapName} ) + throws java.io.IOException + { + XmlSerializer serializer = new MXSerializer(); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-indentation", " " ); + serializer.setProperty( "http://xmlpull.org/v1/doc/properties.html#serializer-line-separator", "\n" ); + serializer.setOutput( stream, ${rootLcapName}.getModelEncoding() ); + serializer.startDocument( ${rootLcapName}.getModelEncoding(), null ); + write${root.name}( "$rootTag", ${rootLcapName}, serializer ); + serializer.endDocument(); + } //-- void write( OutputStream, ${root.name} ) + + /** + * Method writeDomToSerializer. + * + * @param dom a dom object. + * @param serializer a serializer object. + * @throws java.io.IOException java.io.IOException if any. + */ + protected void writeDomToSerializer( org.apache.maven.api.xml.Dom dom, XmlSerializer serializer ) + throws java.io.IOException + { + serializer.startTag( NAMESPACE, dom.getName() ); + + for ( Map.Entry attribute : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attribute.getKey(), attribute.getValue() ); + } + for ( Dom aChild : dom.getChildren() ) + { + writeDomToSerializer( aChild, serializer ); + } + + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + + serializer.endTag( NAMESPACE, dom.getName() ); + + } //-- void writeDomToSerializer( org.apache.maven.api.xml.Dom, XmlSerializer ) + + +#foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) + #set ( $classUcapName = $Helper.capitalise( $class.name ) ) + #set ( $classLcapName = $Helper.uncapitalise( $class.name ) ) + #set ( $allFields = $Helper.xmlFields( $class ) ) + private void write${classUcapName}( String tagName, ${classUcapName} ${classLcapName}, XmlSerializer serializer ) + throws IOException + { + if ( ${classLcapName} != null ) + { + #if ( $class == $root ) + if ( this.fileComment != null ) + { + serializer.comment(this.fileComment); + } + serializer.setPrefix( "", "http://maven.apache.org/POM/4.0.0" ); + serializer.setPrefix( "xsi", "http://www.w3.org/2001/XMLSchema-instance" ); + serializer.startTag( NAMESPACE, tagName ); + serializer.attribute( "", "xsi:schemaLocation", "http://maven.apache.org/POM/4.0.0 https://maven.apache.org/xsd/maven-4.0.0.xsd" ); + #else + serializer.startTag( NAMESPACE, tagName ); + #end + #foreach ( $field in $allFields ) + #if ( $Helper.xmlFieldMetadata( $field ).attribute ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #if ( $field.type == "String" ) + writeAttr( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #else + // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + #foreach ( $field in $allFields ) + #if ( ! $Helper.xmlFieldMetadata( $field ).attribute && ! $Helper.xmlFieldMetadata( $field ).transient ) + #set ( $fieldTagName = $Helper.xmlFieldMetadata( $field ).tagName ) + #if ( ! $fieldTagName ) + #set ( $fieldTagName = $field.name ) + #end + #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) + #if ( $field.type == "String" ) + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName} ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName} ); + #end + #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer, ${classLcapName} ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer, ${classLcapName} ); + #end + #elseif ( $field.type == "int" ) + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer, ${classLcapName} ); + #elseif ( $field.type == "DOM" ) + writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName}, + t -> writeTag( "$singularField", null, t, serializer, null ) ); + #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) + writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName} ); + #elseif ( $field.to && $field.multiplicity == "1" ) + write${field.to}( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); + #elseif ( $field.to && $field.multiplicity == "*" ) + #set( $singularField = ${Helper.singular($fieldTagName)} ) + writeList( "$fieldTagName", $Helper.isFlatItems($field), ${classLcapName}.get${fieldCapName}(), serializer, ${classLcapName}, + t -> write${field.to}( "$singularField", t, serializer ) ); + #else + // TODO: name=${field.name} type=${field.type} to=${field.to} multiplicity=${field.multiplicity} + #end + #end + #end + serializer.endTag( NAMESPACE, tagName ); + writeLocationTracking( ${classLcapName}, "", serializer ); + } + } + + #end +#end + @FunctionalInterface + private interface ElementWriter + { + public void write( T t ) throws IOException; + } + + private void writeList( String tagName, List list, XmlSerializer serializer, InputLocationTracker locationTracker, ElementWriter writer ) + throws IOException + { + writeList( tagName, false, list, serializer, locationTracker, writer ); + } + + private void writeList( String tagName, boolean flat, List list, XmlSerializer serializer, InputLocationTracker locationTracker, ElementWriter writer ) + throws IOException + { + if ( list != null && !list.isEmpty() ) + { + if ( !flat ) + { + serializer.startTag( NAMESPACE, tagName ); + } + int index = 0; + InputLocation location = locationTracker != null ? locationTracker.getLocation( tagName ) : null; + for ( T t : list ) + { + writer.write( t ); + writeLocationTracking( location, Integer.valueOf( index++ ), serializer ); + } + if ( !flat ) + { + serializer.endTag( NAMESPACE, tagName ); + writeLocationTracking( locationTracker, tagName, serializer ); + } + } + } + + private void writeProperties( String tagName, Properties props, XmlSerializer serializer, InputLocationTracker locationTracker ) + throws IOException + { + if ( props != null && !props.isEmpty() ) + { + serializer.startTag( NAMESPACE, tagName ); + InputLocation location = locationTracker != null ? locationTracker.getLocation( tagName ) : null; + for ( Map.Entry entry : props.entrySet() ) + { + String key = entry.getKey().toString(); + writeTag( key, null, entry.getValue().toString(), serializer, null ); + writeLocationTracking( location, key, serializer ); + } + serializer.endTag( NAMESPACE, tagName ); + writeLocationTracking( locationTracker, tagName, serializer ); + } + } + + private void writeDom( Dom dom, XmlSerializer serializer ) + throws IOException + { + if ( dom != null ) + { + serializer.startTag( NAMESPACE, dom.getName() ); + for ( Map.Entry attr : dom.getAttributes().entrySet() ) + { + serializer.attribute( NAMESPACE, attr.getKey(), attr.getValue() ); + } + for ( Dom child : dom.getChildren() ) + { + writeDom( child, serializer ); + } + String value = dom.getValue(); + if ( value != null ) + { + serializer.text( value ); + } + serializer.endTag( NAMESPACE, dom.getName() ); + } + } + + private void writeTag( String tagName, String defaultValue, String value, XmlSerializer serializer, InputLocationTracker locationTracker ) + throws IOException + { + if ( value != null && !Objects.equals( defaultValue, value ) ) + { + serializer.startTag( NAMESPACE, tagName ).text( value ).endTag( NAMESPACE, tagName ); + writeLocationTracking( locationTracker, tagName, serializer ); + } + } + + private void writeAttr( String attrName, String value, XmlSerializer serializer ) + throws IOException + { + if ( value != null ) + { + serializer.attribute( NAMESPACE, attrName, value ); + } + } + + /** + * Method writeLocationTracking. + * + * @param locationTracker + * @param serializer + * @param key + * @throws java.io.IOException + */ + protected void writeLocationTracking( InputLocationTracker locationTracker, Object key, XmlSerializer serializer ) + throws java.io.IOException + { + InputLocation location = ( locationTracker == null ) ? null : locationTracker.getLocation( key ); + if ( location != null ) + { + serializer.comment( toString( location ) ); + } + } //-- void writeLocationTracking( InputLocationTracker, Object, XmlSerializer ) + + /** + * Method toString. + * + * @param location + * @return String + */ + protected String toString( InputLocation location ) + { + if ( stringFormatter != null ) + { + return stringFormatter.toString( location ); + } + return ' ' + location.getSource().toString() + ':' + location.getLineNumber() + ' '; + } //-- String toString( InputLocation ) } From 7be1f2b57cdae0ea66f6aca8976b928b3f333209 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 17:54:49 +0200 Subject: [PATCH 33/98] Improve generated code, fix some compatibility issues with the model --- api/maven-api-model/src/main/mdo/model.vm | 5 +-- api/maven-api-settings/src/main/mdo/model.vm | 8 +++-- api/maven-api-toolchain/src/main/mdo/model.vm | 11 ++++--- maven-model/src/main/mdo/model-v3.vm | 31 +++++++++---------- maven-plugin-api/src/main/mdo/model.vm | 11 ++++--- maven-settings/pom.xml | 8 ++--- maven-settings/src/main/mdo/model-v3.vm | 21 +++++++++++-- maven-toolchain-model/pom.xml | 8 ++--- .../src/main/mdo/model-v3.vm | 21 +++++++++++-- 9 files changed, 81 insertions(+), 43 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 75cf96b89f99..3079f310ab85 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -114,12 +114,13 @@ public class ${class.name} final String modelEncoding; #end #foreach ( $field in $class.allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) /** #foreach ( $line in ${field.description.trim().split("\n")} ) * ${line.trim()} #end */ - final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + final ${type} $field.name; #end #if ( ! $class.superClass ) /** Location of the xml element for this object. */ @@ -244,7 +245,7 @@ public class ${class.name} #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end - public ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + public ${type} ${pfx}${cap}() { return this.${field.name}; } diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm index fbcdeed02895..55e3c29e9411 100644 --- a/api/maven-api-settings/src/main/mdo/model.vm +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -94,7 +94,8 @@ public class ${class.name} final String modelEncoding; #end #foreach ( $field in $class.getFields($version) ) - final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + final ${type} $field.name; #end ${class.name}( @@ -172,7 +173,7 @@ public class ${class.name} #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end - public ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + public ${type} ${pfx}${cap}() { return this.${field.name}; } @@ -283,7 +284,8 @@ public class ${class.name} #end #foreach ( $field in $allFields ) - public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + public Builder ${field.name}( ${type} ${field.name} ) { this.${field.name} = ${field.name}; return this; diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm index fbcdeed02895..5d47aeca9a85 100644 --- a/api/maven-api-toolchain/src/main/mdo/model.vm +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -94,7 +94,8 @@ public class ${class.name} final String modelEncoding; #end #foreach ( $field in $class.getFields($version) ) - final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + final ${type} $field.name; #end ${class.name}( @@ -102,12 +103,13 @@ public class ${class.name} String modelEncoding, #end #foreach ( $field in $allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) #if ( $field == ${allFields[${allFields.size()} - 1]} ) #set ( $sep = "" ) #else #set ( $sep = "," ) #end - ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name${sep} + ${type} $field.name${sep} #end ) { @@ -172,7 +174,7 @@ public class ${class.name} #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end - public ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + public ${type} ${pfx}${cap}() { return this.${field.name}; } @@ -283,7 +285,8 @@ public class ${class.name} #end #foreach ( $field in $allFields ) - public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + public Builder ${field.name}( ${type} ${field.name} ) { this.${field.name} = ${field.name}; return this; diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index e4fc1c7471f5..49e8403acd2f 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -18,6 +18,7 @@ *# #set ( $basePackage = "org.apache.maven.model" ) #set ( $package = "${basePackage}" ) +#set ( $wrapPackage = "org.apache.maven.api.model" ) #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) @@ -33,7 +34,7 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $types = { "DOM": "Object" } ) + #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" ) ) @@ -50,6 +51,9 @@ #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('.') ) @@ -98,15 +102,15 @@ public class ${class.name} public ${class.name}() { - this( org.apache.maven.api.model.${class.name}.newInstance() ); + this( ${wrapPackage}.${class.name}.newInstance() ); } - public ${class.name}( org.apache.maven.api.model.${class.name} delegate ) + public ${class.name}( ${wrapPackage}.${class.name} delegate ) { this( delegate, null ); } - public ${class.name}( org.apache.maven.api.model.${class.name} delegate, BaseObject parent ) + public ${class.name}( ${wrapPackage}.${class.name} delegate, BaseObject parent ) { super( delegate, parent ); } @@ -119,9 +123,9 @@ public class ${class.name} #if ( $class.superClass ) @Override #end - public org.apache.maven.api.model.${class.name} getDelegate() + public ${wrapPackage}.${class.name} getDelegate() { - return ( org.apache.maven.api.model.${class.name} ) super.getDelegate(); + return ( ${wrapPackage}.${class.name} ) super.getDelegate(); } #if ( ! $eq.empty ) @@ -165,7 +169,7 @@ public class ${class.name} #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end - public ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + public ${type} ${pfx}${cap}() { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) return new WrapperList<${field.to}, org.apache.maven.api.model.${field.to}>( @@ -178,23 +182,18 @@ public class ${class.name} #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 org.codehaus.plexus.util.xml.Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; #else return getDelegate().${pfx}${cap}(); #end } - public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + public void set${cap}( ${type} ${field.name} ) { #if ( $field.type == "DOM" ) - if ( ${field.name} instanceof org.codehaus.plexus.util.xml.Xpp3Dom ) - { - ${field.name} = ( ( org.codehaus.plexus.util.xml.Xpp3Dom ) ${field.name} ).getDom(); - } - org.apache.maven.api.xml.Dom dom = ( org.apache.maven.api.xml.Dom ) ${field.name}; - if ( ! Objects.equals( dom, getDelegate().${pfx}${cap}() ) ) + if ( ! Objects.equals( ( ( Xpp3Dom ) ${field.name} ).getDom(), getDelegate().${pfx}${cap}() ) ) { - update( getDelegate().with${cap}( dom ) ); + update( getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ) ); } #else if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) diff --git a/maven-plugin-api/src/main/mdo/model.vm b/maven-plugin-api/src/main/mdo/model.vm index 0bbda40c426a..c925432023da 100644 --- a/maven-plugin-api/src/main/mdo/model.vm +++ b/maven-plugin-api/src/main/mdo/model.vm @@ -91,7 +91,8 @@ public class ${class.name} final String modelEncoding; #end #foreach ( $field in $class.getFields($version) ) - final ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name; + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + final ${type} $field.name; #end ${class.name}( @@ -99,12 +100,13 @@ public class ${class.name} String modelEncoding, #end #foreach ( $field in $allFields ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) #if ( $field == ${allFields[${allFields.size()} - 1]} ) #set ( $sep = "" ) #else #set ( $sep = "," ) #end - ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name${sep} + ${type} $field.name${sep} #end ) { @@ -169,7 +171,7 @@ public class ${class.name} #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end - public ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + public ${type} ${pfx}${cap}() { return this.${field.name}; } @@ -280,7 +282,8 @@ public class ${class.name} #end #foreach ( $field in $allFields ) - public Builder ${field.name}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + public Builder ${field.name}( ${type} ${field.name} ) { this.${field.name} = ${field.name}; return this; diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml index d685b139dbfb..59af2f511de5 100644 --- a/maven-settings/pom.xml +++ b/maven-settings/pom.xml @@ -34,10 +34,6 @@ under the License. Maven Settings model. - - org.codehaus.plexus - plexus-utils - org.apache.maven maven-api-settings @@ -48,6 +44,10 @@ under the License. maven-xml-impl 4.0.0-alpha-1-SNAPSHOT + + org.codehaus.plexus + plexus-utils + diff --git a/maven-settings/src/main/mdo/model-v3.vm b/maven-settings/src/main/mdo/model-v3.vm index 77f01221062c..2d7fa6a55c87 100644 --- a/maven-settings/src/main/mdo/model-v3.vm +++ b/maven-settings/src/main/mdo/model-v3.vm @@ -34,7 +34,7 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #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" ) ) @@ -50,6 +50,9 @@ #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('.') ) @@ -170,7 +173,7 @@ public class ${class.name} #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end - public ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + public ${type} ${pfx}${cap}() { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) return new WrapperList<${field.to}, ${wrapPackage}.${field.to}>( @@ -182,18 +185,22 @@ public class ${class.name} return new WrapperList( 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; + #elseif ( $field.type == "DOM" ) + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; #else return getDelegate().${pfx}${cap}(); #end } - public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + public void set${cap}( ${type} ${field.name} ) { #if ( $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() ); + #elseif ( $field.type == "DOM" ) + delegate = getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ); #else delegate = getDelegate().with${cap}( ${field.name} ); #end @@ -215,6 +222,14 @@ public class ${class.name} #end } + #elseif ( $field.type == "java.util.Properties" && $field.multiplicity == "*" ) + #set ( $v = $Helper.singular( ${field.name} ) ) + #set ( $scap = $Helper.capitalise( $v ) ) + public void add${scap}( String key, String value ) + { + get${cap}().put( key, value ); + } + #end #end public static List<${wrapPackage}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) diff --git a/maven-toolchain-model/pom.xml b/maven-toolchain-model/pom.xml index 5ade9ba8cb96..3362c2473b5e 100644 --- a/maven-toolchain-model/pom.xml +++ b/maven-toolchain-model/pom.xml @@ -35,10 +35,6 @@ under the License. Maven Toolchain model. - - org.codehaus.plexus - plexus-utils - org.apache.maven maven-api-toolchain @@ -49,6 +45,10 @@ under the License. maven-xml-impl 4.0.0-alpha-1-SNAPSHOT + + org.codehaus.plexus + plexus-utils + diff --git a/maven-toolchain-model/src/main/mdo/model-v3.vm b/maven-toolchain-model/src/main/mdo/model-v3.vm index 11bb72f10fe7..f0e1f39d5a8f 100644 --- a/maven-toolchain-model/src/main/mdo/model-v3.vm +++ b/maven-toolchain-model/src/main/mdo/model-v3.vm @@ -34,7 +34,7 @@ #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #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" ) ) @@ -50,6 +50,9 @@ #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('.') ) @@ -170,7 +173,7 @@ public class ${class.name} #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end - public ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${pfx}${cap}() + public ${type} ${pfx}${cap}() { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) return new WrapperList<${field.to}, ${wrapPackage}.${field.to}>( @@ -182,18 +185,22 @@ public class ${class.name} return new WrapperList( 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; + #elseif ( $field.type == "DOM" ) + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}() ) : null; #else return getDelegate().${pfx}${cap}(); #end } - public void set${cap}( ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ${field.name} ) + public void set${cap}( ${type} ${field.name} ) { #if ( $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() ); + #elseif ( $field.type == "DOM" ) + delegate = getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ); #else delegate = getDelegate().with${cap}( ${field.name} ); #end @@ -215,6 +222,14 @@ public class ${class.name} #end } + #elseif ( $field.type == "java.util.Properties" && $field.multiplicity == "*" ) + #set ( $v = $Helper.singular( ${field.name} ) ) + #set ( $scap = $Helper.capitalise( $v ) ) + public void add${scap}( String key, String value ) + { + get${cap}().put( key, value ); + } + #end #end public static List<${wrapPackage}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) From 1e97b4a682f5194d3c6b71583e05606814a0c207 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 17:55:14 +0200 Subject: [PATCH 34/98] Restore ToolchainFactory compatibility --- .../maven/toolchain/DefaultToolchain.java | 2 +- .../toolchain/DefaultToolchainManager.java | 4 +- .../DefaultToolchainManagerPrivate.java | 4 +- .../maven/toolchain/ToolchainFactory.java | 3 +- .../maven/toolchain/ToolchainPrivate.java | 2 +- .../toolchain/java/DefaultJavaToolChain.java | 2 +- .../toolchain/java/JavaToolchainFactory.java | 8 +-- .../toolchain/java/JavaToolchainImpl.java | 2 +- .../DefaultToolchainManagerTest.java | 38 +++++------ .../maven/toolchain/DefaultToolchainTest.java | 65 +++++++++---------- 10 files changed, 63 insertions(+), 67 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java index 2b248512e817..8b44552b1414 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchain.java @@ -25,7 +25,7 @@ import java.util.Properties; import java.util.Objects; -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; import org.slf4j.Logger; /** diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java index 6b101b440d47..a5fa002c2e3c 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java @@ -115,7 +115,9 @@ private List selectToolchains( List models, String ty { try { - ToolchainPrivate toolchain = fact.createToolchain( model ); + org.apache.maven.toolchain.model.ToolchainModel tm = + new org.apache.maven.toolchain.model.ToolchainModel( model ); + ToolchainPrivate toolchain = fact.createToolchain( tm ); if ( requirements == null || toolchain.matchesRequirements( requirements ) ) { toolchains.add( toolchain ); diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java index 8e16bad93316..bd4df0188ba6 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManagerPrivate.java @@ -79,7 +79,9 @@ public ToolchainPrivate[] getToolchainsForType( String type, MavenSession sessio { for ( ToolchainModel toolchainModel : availableToolchains ) { - toRet.add( fact.createToolchain( toolchainModel ) ); + org.apache.maven.toolchain.model.ToolchainModel tm = + new org.apache.maven.toolchain.model.ToolchainModel( toolchainModel ); + toRet.add( fact.createToolchain( tm ) ); } } diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java index a91bac6c5006..c99a3cd8ac96 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainFactory.java @@ -19,7 +19,8 @@ * under the License. */ -import org.apache.maven.api.toolchain.ToolchainModel; + +import org.apache.maven.toolchain.model.ToolchainModel; /** * Internal toolchain factory, to prepare toolchains instances. diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java index 138bb2caa110..90e0f305635e 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/ToolchainPrivate.java @@ -21,7 +21,7 @@ import java.util.Map; -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; /** * a private contract between the toolchains plugin and the components. diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java b/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java index 70d5f00af8f9..e264e601fde0 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/java/DefaultJavaToolChain.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; import org.slf4j.Logger; /** diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java index 688cf9101733..09c721fa88fd 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainFactory.java @@ -26,14 +26,14 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.api.xml.Dom; import org.apache.maven.toolchain.MisconfiguredToolchainException; import org.apache.maven.toolchain.RequirementMatcher; import org.apache.maven.toolchain.RequirementMatcherFactory; import org.apache.maven.toolchain.ToolchainFactory; import org.apache.maven.toolchain.ToolchainPrivate; -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; import org.codehaus.plexus.util.FileUtils; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -92,8 +92,8 @@ public ToolchainPrivate createToolchain( ToolchainModel model ) } // populate the configuration section - Dom dom = model.getConfiguration(); - Dom javahome = dom.getChild( JavaToolchainImpl.KEY_JAVAHOME ); + Xpp3Dom dom = ( Xpp3Dom ) model.getConfiguration(); + Xpp3Dom javahome = dom != null ? dom.getChild( JavaToolchainImpl.KEY_JAVAHOME ) : null; if ( javahome == null ) { throw new MisconfiguredToolchainException( "Java toolchain without the " diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java index 65009d3977c3..af5a88cc42ef 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/java/JavaToolchainImpl.java @@ -22,7 +22,7 @@ import java.io.File; import org.apache.maven.toolchain.DefaultToolchain; -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; import org.codehaus.plexus.util.FileUtils; import org.codehaus.plexus.util.Os; import org.slf4j.Logger; diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java index ca30fd18eee9..893f55f044cd 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainManagerTest.java @@ -34,7 +34,7 @@ import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentMatchers; @@ -45,7 +45,7 @@ public class DefaultToolchainManagerTest { - // Mocks to inject into toolchainManager + // Mocks to inject into toolchainManager @Mock private Logger logger; @@ -86,8 +86,8 @@ public void testModelNoFactory() { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "unknown", Collections.singletonList( newToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "unknown", Collections.singletonList( new ToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); @@ -102,9 +102,9 @@ public void testModelAndFactory() { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "basic", Arrays.asList( newToolchainModel(), newToolchainModel() ) ); - toolchainModels.put( "rare", Collections.singletonList( newToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "basic", Arrays.asList( new ToolchainModel(), new ToolchainModel() ) ); + toolchainModels.put( "rare", Collections.singletonList( new ToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); @@ -118,9 +118,9 @@ public void testModelsAndFactory() { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "basic", Arrays.asList( newToolchainModel(), newToolchainModel() ) ); - toolchainModels.put( "rare", Collections.singletonList( newToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "basic", Arrays.asList( new ToolchainModel(), new ToolchainModel() ) ); + toolchainModels.put( "rare", Collections.singletonList( new ToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); @@ -131,13 +131,13 @@ public void testModelsAndFactory() @Test public void testRequirements() - throws Exception + throws Exception { MavenSession session = mock( MavenSession.class ); MavenExecutionRequest executionRequest = new DefaultMavenExecutionRequest(); - Map> toolchainModels = new HashMap<>(); - toolchainModels.put( "basic", Arrays.asList( newToolchainModel(), newToolchainModel() ) ); - toolchainModels.put( "rare", Collections.singletonList( newToolchainModel() ) ); + Map> toolchainModels = new HashMap<>(); + toolchainModels.put( "basic", Arrays.asList( new ToolchainModel(), new ToolchainModel() ) ); + toolchainModels.put( "rare", Collections.singletonList( new ToolchainModel() ) ); executionRequest.setToolchains( toolchainModels ); when( session.getRequest() ).thenReturn( executionRequest ); ToolchainPrivate basicPrivate = mock( ToolchainPrivate.class ); @@ -145,14 +145,8 @@ public void testRequirements() when( toolchainFactory_basicType.createToolchain( isA( ToolchainModel.class ) ) ).thenReturn( basicPrivate ); List toolchains = - toolchainManager.getToolchains( session, "basic", Collections.singletonMap( "key", "value" ) ); + toolchainManager.getToolchains( session, "basic", Collections.singletonMap( "key", "value" ) ); assertEquals( 1, toolchains.size() ); } - - private org.apache.maven.toolchain.model.ToolchainModel newToolchainModel() - { - return new org.apache.maven.toolchain.model.ToolchainModel( ToolchainModel.newInstance() ); - } - -} +} \ No newline at end of file diff --git a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java index fd6d66bb778b..509e014a2375 100644 --- a/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java +++ b/maven-core/src/test/java/org/apache/maven/toolchain/DefaultToolchainTest.java @@ -26,11 +26,10 @@ import static org.mockito.Mockito.verify; import java.util.Collections; -import java.util.Properties; -import org.apache.maven.internal.xml.Xpp3Dom; import org.apache.maven.toolchain.java.DefaultJavaToolChain; -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; import org.mockito.MockitoAnnotations; @@ -42,7 +41,7 @@ public class DefaultToolchainTest @BeforeEach public void setUp() - throws Exception + throws Exception { MockitoAnnotations.initMocks( this ); } @@ -74,7 +73,7 @@ public String findTool( String toolName ) @Test public void testGetModel() { - ToolchainModel model = ToolchainModel.newInstance(); + ToolchainModel model = new ToolchainModel(); DefaultToolchain toolchain = newDefaultToolchain( model ); assertEquals( model, toolchain.getModel() ); } @@ -82,11 +81,11 @@ public void testGetModel() @Test public void testGetType() { - ToolchainModel model = ToolchainModel.newInstance(); + ToolchainModel model = new ToolchainModel(); DefaultToolchain toolchain = newDefaultToolchain( model, "TYPE" ); assertEquals( "TYPE", toolchain.getType() ); - model = model.withType( "MODEL_TYPE" ); + model.setType( "MODEL_TYPE" ); toolchain = newDefaultToolchain( model ); assertEquals( "MODEL_TYPE", toolchain.getType() ); } @@ -94,7 +93,7 @@ public void testGetType() @Test public void testGetLogger() { - ToolchainModel model = ToolchainModel.newInstance(); + ToolchainModel model = new ToolchainModel(); DefaultToolchain toolchain = newDefaultToolchain( model ); assertEquals( logger, toolchain.getLog() ); } @@ -102,8 +101,8 @@ public void testGetLogger() @Test public void testMissingRequirementProperty() { - ToolchainModel model = ToolchainModel.newInstance(); - model = model.withType( "TYPE" ); + ToolchainModel model = new ToolchainModel(); + model.setType( "TYPE" ); DefaultToolchain toolchain = newDefaultToolchain( model ); assertFalse( toolchain.matchesRequirements( Collections.singletonMap( "name", "John Doe" ) ) ); @@ -114,8 +113,8 @@ public void testMissingRequirementProperty() @Test public void testNonMatchingRequirementProperty() { - ToolchainModel model = ToolchainModel.newInstance(); - model = model.withType( "TYPE" ); + ToolchainModel model = new ToolchainModel(); + model.setType( "TYPE" ); DefaultToolchain toolchain = newDefaultToolchain( model ); toolchain.addProvideToken( "name", RequirementMatcherFactory.createExactMatcher( "Jane Doe" ) ); @@ -127,27 +126,25 @@ public void testNonMatchingRequirementProperty() @Test public void testEquals() { - Properties props1 = new Properties(); - props1.put( "version", "1.5" ); - props1.put( "vendor", "sun" ); - Xpp3Dom jdkHome1 = new Xpp3Dom( "jdkHome", "${env.JAVA_HOME}", null, null, null ); - Xpp3Dom configuration1 = new Xpp3Dom("configuration", null, null, Collections.singletonList( jdkHome1 ), null ); - ToolchainModel tm1 = ToolchainModel.newBuilder() - .type( "jdk" ) - .provides( props1 ) - .configuration( configuration1 ) - .build(); - - Properties props2 = new Properties(); - props2.put( "version", "1.4" ); - props2.put( "vendor", "sun" ); - Xpp3Dom jdkHome2 = new Xpp3Dom( "jdkHome", "${env.JAVA_HOME}", null, null, null ); - Xpp3Dom configuration2 = new Xpp3Dom("configuration", null, null, Collections.singletonList( jdkHome2 ), null ); - ToolchainModel tm2 = ToolchainModel.newBuilder() - .type( "jdk" ) - .provides( props2 ) - .configuration( configuration2 ) - .build(); + ToolchainModel tm1 = new ToolchainModel(); + tm1.setType( "jdk" ); + tm1.addProvide( "version", "1.5" ); + tm1.addProvide( "vendor", "sun" ); + Xpp3Dom configuration1 = new Xpp3Dom("configuration"); + Xpp3Dom jdkHome1 = new Xpp3Dom( "jdkHome" ); + jdkHome1.setValue("${env.JAVA_HOME}"); + configuration1.addChild( jdkHome1 ); + tm1.setConfiguration( configuration1 ); + + ToolchainModel tm2 = new ToolchainModel(); + tm1.setType( "jdk" ); + tm1.addProvide( "version", "1.4" ); + tm1.addProvide( "vendor", "sun" ); + Xpp3Dom configuration2 = new Xpp3Dom("configuration"); + Xpp3Dom jdkHome2 = new Xpp3Dom( "jdkHome" ); + jdkHome2.setValue("${env.JAVA_HOME}"); + configuration2.addChild( jdkHome2 ); + tm2.setConfiguration( configuration2 ); DefaultToolchain tc1 = new DefaultJavaToolChain( tm1, null ); DefaultToolchain tc2 = new DefaultJavaToolChain( tm2, null ); @@ -157,4 +154,4 @@ public void testEquals() assertNotEquals( tc2, tc1 ); assertEquals( tc2, tc2 ); } -} +} \ No newline at end of file From 79f3d09ce7b23dcda98a61d15b9cff92a0de184f Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 18:07:49 +0200 Subject: [PATCH 35/98] Fix class cast exception --- .../lifecycle/internal/DefaultLifecyclePluginAnalyzer.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java index 119151137ac7..c52eda83a59d 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecyclePluginAnalyzer.java @@ -40,6 +40,7 @@ import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -224,7 +225,7 @@ private void parseLifecyclePhaseDefinitions( Map plugins, String Dom lifecycleConfiguration = mojo.getConfiguration(); if ( lifecycleConfiguration != null ) { - execution.setConfiguration( lifecycleConfiguration ); + execution.setConfiguration( new Xpp3Dom( lifecycleConfiguration ) ); } if ( mojo.getDependencies() != null ) From 22da4a6bff35f61579ee04b9e765492344896f60 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 20:55:40 +0200 Subject: [PATCH 36/98] Use pom parameters for package names --- maven-model/pom.xml | 5 +++++ maven-model/src/main/mdo/merger.vm | 7 +++--- maven-model/src/main/mdo/model-v3.vm | 16 +++++++------- maven-model/src/main/mdo/reader-ex.vm | 15 +++++-------- maven-model/src/main/mdo/reader.vm | 15 +++++-------- maven-model/src/main/mdo/transformer.vm | 6 ++--- maven-model/src/main/mdo/writer-ex.vm | 7 +++--- maven-model/src/main/mdo/writer.vm | 7 +++--- maven-settings/pom.xml | 5 +++++ maven-settings/src/main/mdo/merger.vm | 7 +++--- maven-settings/src/main/mdo/model-v3.vm | 22 +++++++++---------- maven-settings/src/main/mdo/reader.vm | 7 +++--- maven-settings/src/main/mdo/writer.vm | 7 +++--- maven-toolchain-model/pom.xml | 5 +++++ maven-toolchain-model/src/main/mdo/merger.vm | 7 +++--- .../src/main/mdo/model-v3.vm | 22 +++++++++---------- maven-toolchain-model/src/main/mdo/reader.vm | 7 +++--- maven-toolchain-model/src/main/mdo/writer.vm | 7 +++--- 18 files changed, 94 insertions(+), 80 deletions(-) diff --git a/maven-model/pom.xml b/maven-model/pom.xml index e4e4b5d312e7..d71c06e6cc64 100644 --- a/maven-model/pom.xml +++ b/maven-model/pom.xml @@ -104,6 +104,11 @@ under the License. + + packageModelV3=org.apache.maven.model + packageModelV4=org.apache.maven.api.model + packageToolV4=org.apache.maven.model.v4 + diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm index ffc06d2e9bcb..bb6954ba38aa 100644 --- a/maven-model/src/main/mdo/merger.vm +++ b/maven-model/src/main/mdo/merger.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.model" ) -#set ( $package = "org.apache.maven.model.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "ModelMerger" ) +# #foreach ( $field in $model.getClass("Model", $version).allFields ) #if ( $field.name == "pomFile" ) #set ( $dummy = $field.setType("java.nio.file.Path") ) @@ -49,7 +50,7 @@ import java.util.stream.Collectors; import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.Name}; +import ${packageModelV4}.${class.Name}; #end @Generated diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 49e8403acd2f..edf5b3437c02 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -16,9 +16,9 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.model" ) -#set ( $package = "${basePackage}" ) -#set ( $wrapPackage = "org.apache.maven.api.model" ) +# +#set ( $package = "${packageModelV3}" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) @@ -102,15 +102,15 @@ public class ${class.name} public ${class.name}() { - this( ${wrapPackage}.${class.name}.newInstance() ); + this( ${packageModelV4}.${class.name}.newInstance() ); } - public ${class.name}( ${wrapPackage}.${class.name} delegate ) + public ${class.name}( ${packageModelV4}.${class.name} delegate ) { this( delegate, null ); } - public ${class.name}( ${wrapPackage}.${class.name} delegate, BaseObject parent ) + public ${class.name}( ${packageModelV4}.${class.name} delegate, BaseObject parent ) { super( delegate, parent ); } @@ -123,9 +123,9 @@ public class ${class.name} #if ( $class.superClass ) @Override #end - public ${wrapPackage}.${class.name} getDelegate() + public ${packageModelV4}.${class.name} getDelegate() { - return ( ${wrapPackage}.${class.name} ) super.getDelegate(); + return ( ${packageModelV4}.${class.name} ) super.getDelegate(); } #if ( ! $eq.empty ) diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm index 726c60e1e2a8..e2931925a472 100644 --- a/maven-model/src/main/mdo/reader-ex.vm +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.model" ) -#set ( $package = "org.apache.maven.model.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "MavenXpp3ReaderEx" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -46,7 +47,7 @@ import java.util.Set; import org.apache.maven.api.annotations.Generated; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; @@ -63,13 +64,7 @@ public class ${className} public ${className}() { - this( new ContentTransformer() - { - public String transform( String source, String fieldName ) - { - return source; - } - } ); + this( ( s, f ) -> s ); } public ${className}( ContentTransformer contentTransformer ) diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm index c5cee0d6c2c9..a1a52b121856 100644 --- a/maven-model/src/main/mdo/reader.vm +++ b/maven-model/src/main/mdo/reader.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.model" ) -#set ( $package = "org.apache.maven.model.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "MavenXpp3Reader" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -44,7 +45,7 @@ import java.util.Set; import org.apache.maven.api.annotations.Generated; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; @@ -61,13 +62,7 @@ public class ${className} public ${className}() { - this( new ContentTransformer() - { - public String transform( String source, String fieldName ) - { - return source; - } - } ); + this( ( s, f ) -> s ); } public ${className}( ContentTransformer contentTransformer ) diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm index fb2817ca7338..882d639aaa9b 100644 --- a/maven-model/src/main/mdo/transformer.vm +++ b/maven-model/src/main/mdo/transformer.vm @@ -16,8 +16,8 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.model" ) -#set ( $package = "org.apache.maven.model.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "ModelTransformer" ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java @@ -44,7 +44,7 @@ import java.util.stream.Collectors; import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.xml.Xpp3Dom; diff --git a/maven-model/src/main/mdo/writer-ex.vm b/maven-model/src/main/mdo/writer-ex.vm index 737ec8e32fab..0ffb6c746db8 100644 --- a/maven-model/src/main/mdo/writer-ex.vm +++ b/maven-model/src/main/mdo/writer-ex.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.model" ) -#set ( $package = "org.apache.maven.model.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "MavenXpp3WriterEx" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -50,7 +51,7 @@ import org.apache.maven.api.model.InputLocationTracker; import org.apache.maven.api.xml.Dom; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; diff --git a/maven-model/src/main/mdo/writer.vm b/maven-model/src/main/mdo/writer.vm index 5ba0561da42b..bcf705f89c85 100644 --- a/maven-model/src/main/mdo/writer.vm +++ b/maven-model/src/main/mdo/writer.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.model" ) -#set ( $package = "org.apache.maven.model.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "MavenXpp3Writer" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -49,7 +50,7 @@ import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; diff --git a/maven-settings/pom.xml b/maven-settings/pom.xml index 59af2f511de5..2410260b5535 100644 --- a/maven-settings/pom.xml +++ b/maven-settings/pom.xml @@ -100,6 +100,11 @@ under the License. + + packageModelV3=org.apache.maven.settings + packageModelV4=org.apache.maven.api.settings + packageToolV4=org.apache.maven.settings.v4 + diff --git a/maven-settings/src/main/mdo/merger.vm b/maven-settings/src/main/mdo/merger.vm index ce30e8cbe515..bbb9d9179ded 100644 --- a/maven-settings/src/main/mdo/merger.vm +++ b/maven-settings/src/main/mdo/merger.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.settings" ) -#set ( $package = "org.apache.maven.settings.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Merger" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -49,7 +50,7 @@ import java.util.stream.Collectors; import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.Name}; +import ${packageModelV4}.${class.Name}; #end @Generated diff --git a/maven-settings/src/main/mdo/model-v3.vm b/maven-settings/src/main/mdo/model-v3.vm index 2d7fa6a55c87..31f6a8f9fb70 100644 --- a/maven-settings/src/main/mdo/model-v3.vm +++ b/maven-settings/src/main/mdo/model-v3.vm @@ -16,9 +16,9 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.settings" ) -#set ( $package = "${basePackage}" ) -#set ( $wrapPackage = "org.apache.maven.api.settings" ) +# +#set ( $package = "${packageModelV3}" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) @@ -98,15 +98,15 @@ public class ${class.name} { #if ( ! $class.superClass ) - ${wrapPackage}.${class.name} delegate; + ${packageModelV4}.${class.name} delegate; #end public ${class.name}() { - this( ${wrapPackage}.${class.name}.newInstance() ); + this( ${packageModelV4}.${class.name}.newInstance() ); } - public ${class.name}( ${wrapPackage}.${class.name} delegate ) + public ${class.name}( ${packageModelV4}.${class.name} delegate ) { #if ( $class.superClass ) super( delegate ); @@ -123,10 +123,10 @@ public class ${class.name} #if ( $class.superClass ) @Override #end - public ${wrapPackage}.${class.name} getDelegate() + public ${packageModelV4}.${class.name} getDelegate() { #if ( $class.superClass ) - return ( ${wrapPackage}.${class.name} ) delegate; + return ( ${packageModelV4}.${class.name} ) delegate; #else return delegate; #end @@ -176,7 +176,7 @@ public class ${class.name} public ${type} ${pfx}${cap}() { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - return new WrapperList<${field.to}, ${wrapPackage}.${field.to}>( + return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>( getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), ${field.to}::new, ${field.to}::getDelegate ); #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" ) @@ -232,12 +232,12 @@ public class ${class.name} #end #end - public static List<${wrapPackage}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) + 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<${wrapPackage}.${class.name}> list ) + 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; } diff --git a/maven-settings/src/main/mdo/reader.vm b/maven-settings/src/main/mdo/reader.vm index 946bc2d5c23b..15960ecd7283 100644 --- a/maven-settings/src/main/mdo/reader.vm +++ b/maven-settings/src/main/mdo/reader.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.settings" ) -#set ( $package = "org.apache.maven.settings.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Reader" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -44,7 +45,7 @@ import java.util.Set; import org.apache.maven.api.annotations.Generated; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; diff --git a/maven-settings/src/main/mdo/writer.vm b/maven-settings/src/main/mdo/writer.vm index a34ba83ecf1e..9afca2daa603 100644 --- a/maven-settings/src/main/mdo/writer.vm +++ b/maven-settings/src/main/mdo/writer.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.settings" ) -#set ( $package = "org.apache.maven.settings.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Writer" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -49,7 +50,7 @@ import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; diff --git a/maven-toolchain-model/pom.xml b/maven-toolchain-model/pom.xml index 3362c2473b5e..a0a8b0bdfc49 100644 --- a/maven-toolchain-model/pom.xml +++ b/maven-toolchain-model/pom.xml @@ -101,6 +101,11 @@ under the License. + + packageModelV3=org.apache.maven.toolchain.model + packageModelV4=org.apache.maven.api.toolchain + packageToolV4=org.apache.maven.toolchain.v4 + diff --git a/maven-toolchain-model/src/main/mdo/merger.vm b/maven-toolchain-model/src/main/mdo/merger.vm index 749725ffa1c3..bbb9d9179ded 100644 --- a/maven-toolchain-model/src/main/mdo/merger.vm +++ b/maven-toolchain-model/src/main/mdo/merger.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.toolchain" ) -#set ( $package = "org.apache.maven.toolchain.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Merger" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -49,7 +50,7 @@ import java.util.stream.Collectors; import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.Name}; +import ${packageModelV4}.${class.Name}; #end @Generated diff --git a/maven-toolchain-model/src/main/mdo/model-v3.vm b/maven-toolchain-model/src/main/mdo/model-v3.vm index f0e1f39d5a8f..31f6a8f9fb70 100644 --- a/maven-toolchain-model/src/main/mdo/model-v3.vm +++ b/maven-toolchain-model/src/main/mdo/model-v3.vm @@ -16,9 +16,9 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.toolchain.model" ) -#set ( $package = "${basePackage}" ) -#set ( $wrapPackage = "org.apache.maven.api.toolchain" ) +# +#set ( $package = "${packageModelV3}" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #foreach ( $class in $model.allClasses ) @@ -98,15 +98,15 @@ public class ${class.name} { #if ( ! $class.superClass ) - ${wrapPackage}.${class.name} delegate; + ${packageModelV4}.${class.name} delegate; #end public ${class.name}() { - this( ${wrapPackage}.${class.name}.newInstance() ); + this( ${packageModelV4}.${class.name}.newInstance() ); } - public ${class.name}( ${wrapPackage}.${class.name} delegate ) + public ${class.name}( ${packageModelV4}.${class.name} delegate ) { #if ( $class.superClass ) super( delegate ); @@ -123,10 +123,10 @@ public class ${class.name} #if ( $class.superClass ) @Override #end - public ${wrapPackage}.${class.name} getDelegate() + public ${packageModelV4}.${class.name} getDelegate() { #if ( $class.superClass ) - return ( ${wrapPackage}.${class.name} ) delegate; + return ( ${packageModelV4}.${class.name} ) delegate; #else return delegate; #end @@ -176,7 +176,7 @@ public class ${class.name} public ${type} ${pfx}${cap}() { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - return new WrapperList<${field.to}, ${wrapPackage}.${field.to}>( + return new WrapperList<${field.to}, ${packageModelV4}.${field.to}>( getDelegate()::get${cap}, l -> delegate = getDelegate().with${cap}( l ), ${field.to}::new, ${field.to}::getDelegate ); #elseif ( $field.to == "String" && $field.type == "java.util.Properties" && $field.multiplicity == "*" ) @@ -232,12 +232,12 @@ public class ${class.name} #end #end - public static List<${wrapPackage}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) + 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<${wrapPackage}.${class.name}> list ) + 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; } diff --git a/maven-toolchain-model/src/main/mdo/reader.vm b/maven-toolchain-model/src/main/mdo/reader.vm index df0c28237315..15960ecd7283 100644 --- a/maven-toolchain-model/src/main/mdo/reader.vm +++ b/maven-toolchain-model/src/main/mdo/reader.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.toolchain" ) -#set ( $package = "org.apache.maven.toolchain.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Reader" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -44,7 +45,7 @@ import java.util.Set; import org.apache.maven.api.annotations.Generated; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm index cc5588329521..5e814a69afcb 100644 --- a/maven-toolchain-model/src/main/mdo/writer.vm +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "org.apache.maven.api.toolchain" ) -#set ( $package = "org.apache.maven.toolchain.v4" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Writer" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -49,7 +50,7 @@ import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; From 0502e73b2104a2a2911670654b4317ef23de7c4d Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 7 Apr 2022 20:56:53 +0200 Subject: [PATCH 37/98] Use the existing variable --- maven-toolchain-model/src/main/mdo/writer.vm | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm index 5e814a69afcb..9afca2daa603 100644 --- a/maven-toolchain-model/src/main/mdo/writer.vm +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -210,7 +210,7 @@ public class ${className} writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); #end #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - #if ( ${field.defaultValue} == "true" ) + #if ( ${def} == "true" ) writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); #else writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); @@ -221,7 +221,7 @@ public class ${className} writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) #set( $singularField = ${Helper.singular($fieldTagName)} ) - writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.to && $field.multiplicity == "1" ) From a1f7d29519c62bc15cb0ce882eebbde4831a7c07 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 11:13:09 +0200 Subject: [PATCH 38/98] Use the same templates --- api/maven-api-model/pom.xml | 2 +- api/maven-api-model/src/main/mdo/common.vm | 31 + api/maven-api-model/src/main/mdo/model.vm | 126 +-- api/maven-api-settings/pom.xml | 2 +- .../api/settings/ImmutableCollections.java | 738 ++++++++++++++++++ .../maven/api/settings/ROProperties.java | 120 --- api/maven-api-settings/src/main/mdo/common.vm | 21 + api/maven-api-settings/src/main/mdo/model.vm | 237 +++++- api/maven-api-toolchain/pom.xml | 2 +- .../api/toolchain/ImmutableCollections.java | 738 ++++++++++++++++++ .../maven/api/toolchain/ROProperties.java | 120 --- .../src/main/mdo/common.vm | 21 + api/maven-api-toolchain/src/main/mdo/model.vm | 236 +++++- .../model/building/DefaultModelBuilder.java | 6 +- .../model/building/FileToRawModelMerger.java | 4 +- .../StringVisitorModelInterpolator.java | 4 +- .../maven/model/merge/MavenModelMerger.java | 4 +- .../building/FileToRawModelMergerTest.java | 4 +- maven-model/src/main/mdo/common.vm | 31 + maven-model/src/main/mdo/merger.vm | 27 +- maven-model/src/main/mdo/model-v3.vm | 1 + maven-model/src/main/mdo/reader-ex.vm | 3 +- maven-model/src/main/mdo/reader.vm | 3 +- maven-model/src/main/mdo/transformer.vm | 3 +- maven-model/src/main/mdo/writer-ex.vm | 3 +- maven-model/src/main/mdo/writer.vm | 3 +- ...elMergerTest.java => MavenMergerTest.java} | 18 +- maven-plugin-api/pom.xml | 5 + .../lifecycle/ImmutableCollections.java | 738 ++++++++++++++++++ maven-plugin-api/src/main/mdo/common.vm | 21 + maven-plugin-api/src/main/mdo/merger.vm | 37 +- maven-plugin-api/src/main/mdo/model.vm | 241 +++++- maven-plugin-api/src/main/mdo/reader.vm | 16 +- maven-plugin-api/src/main/mdo/writer.vm | 25 +- maven-settings/src/main/mdo/common.vm | 21 + maven-settings/src/main/mdo/merger.vm | 30 +- maven-settings/src/main/mdo/model-v3.vm | 1 + maven-settings/src/main/mdo/reader.vm | 9 +- maven-settings/src/main/mdo/writer.vm | 1 + maven-toolchain-model/src/main/mdo/common.vm | 21 + maven-toolchain-model/src/main/mdo/merger.vm | 30 +- .../src/main/mdo/model-v3.vm | 1 + maven-toolchain-model/src/main/mdo/reader.vm | 9 +- maven-toolchain-model/src/main/mdo/writer.vm | 1 + 44 files changed, 3242 insertions(+), 473 deletions(-) create mode 100644 api/maven-api-model/src/main/mdo/common.vm create mode 100644 api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ImmutableCollections.java delete mode 100644 api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java create mode 100644 api/maven-api-settings/src/main/mdo/common.vm create mode 100644 api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ImmutableCollections.java delete mode 100644 api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java create mode 100644 api/maven-api-toolchain/src/main/mdo/common.vm create mode 100644 maven-model/src/main/mdo/common.vm rename maven-model/src/test/java/org/apache/maven/model/merge/{ModelMergerTest.java => MavenMergerTest.java} (96%) create mode 100644 maven-plugin-api/src/main/java/org/apache/maven/plugin/lifecycle/ImmutableCollections.java create mode 100644 maven-plugin-api/src/main/mdo/common.vm create mode 100644 maven-settings/src/main/mdo/common.vm create mode 100644 maven-toolchain-model/src/main/mdo/common.vm diff --git a/api/maven-api-model/pom.xml b/api/maven-api-model/pom.xml index c780cdf04e50..a62c6c72b2ae 100644 --- a/api/maven-api-model/pom.xml +++ b/api/maven-api-model/pom.xml @@ -77,7 +77,7 @@ under the License. - basePackage=org.apache.maven.api.model + packageModelV4=org.apache.maven.api.model diff --git a/api/maven-api-model/src/main/mdo/common.vm b/api/maven-api-model/src/main/mdo/common.vm new file mode 100644 index 000000000000..3c3f29cf7a27 --- /dev/null +++ b/api/maven-api-model/src/main/mdo/common.vm @@ -0,0 +1,31 @@ +#* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*# +# +## +## The following loop code is required in order to change the type of the +## pomFile attribute to a java.nio.file.Path. Modello does not support this +## type and loading a model with such a type would fail the modello validation. +## +#foreach ( $field in $model.getClass("Model", $version).allFields ) + #if ( $field.name == "pomFile" ) + #set ( $dummy = $field.setType("java.nio.file.Path") ) + #end +#end +#set ( $locationTracking = true ) +# \ No newline at end of file diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 3079f310ab85..c981c2bd5138 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -16,18 +16,9 @@ specific language governing permissions and limitations under the License. *# -## -## The following loop code is required in order to change the type of the -## pomFile attribute to a java.nio.file.Path. Modello does not support this -## type and loading a model with such a type would fail the modello validation. -## -#foreach ( $field in $model.getClass("Model", $version).allFields ) - #if ( $field.name == "pomFile" ) - #set ( $dummy = $field.setType("java.nio.file.Path") ) - #end -#end +#parse ( "src/main/mdo/common.vm" ) # -#set ( $package = "${basePackage}" ) +#set ( $package = "${packageModelV4}" ) #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) @@ -35,9 +26,9 @@ #set ( $inheritedFields = [] ) #foreach ( $cl in $ancestors ) #if ( $cl != $class ) - #set ( $dummy = $inheritedFields.addAll( $cl.allFields ) ) + #set ( $dummy = $inheritedFields.addAll( $cl.getFields($version) ) ) #end - #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) #end #set ( $className = "${class.name}" ) #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java @@ -94,26 +85,30 @@ // ============================================================== package ${package}; - #foreach ( $imp in $imports ) + #foreach ( $imp in $imports ) import $imp; - #end + #end /** -#foreach ( $line in ${class.description.trim().split("\n")} ) + #foreach ( $line in ${class.description.trim().split("\n")} ) * ${line.trim()} -#end + #end */ @Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) extends ${class.superClass} #end + #if ( $locationTracking ) implements Serializable, InputLocationTracker + #else + implements Serializable + #end { #if ( $class == $root ) final String modelEncoding; #end - #foreach ( $field in $class.allFields ) + #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) /** #foreach ( $line in ${field.description.trim().split("\n")} ) @@ -122,17 +117,19 @@ public class ${class.name} */ final ${type} $field.name; #end - #if ( ! $class.superClass ) + #if ( $locationTracking ) + #if ( ! $class.superClass ) /** Location of the xml element for this object. */ final InputLocation location; - #end - #foreach ( $field in $class.allFields ) + #end + #foreach ( $field in $class.getFields($version) ) /** Location of the xml element for the field ${field.name}. */ final InputLocation ${field.name}Location; - #end - #if ( ! $class.superClass ) + #end + #if ( ! $class.superClass ) /** Other locations */ final Map locations; + #end #end /** @@ -144,57 +141,57 @@ public class ${class.name} String modelEncoding, #end #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) #if ( $type.startsWith("List<") ) #set ( $type = ${type.replace('List<','Collection<')} ) #end - $type $field.name, + $type $field.name${sep} #end + #if ( $locationTracking ) Map locations, InputLocation location, - #foreach ( $field in $allFields ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) InputLocation ${field.name}Location${sep} + #end #end ) { #if ( $class.superClass ) super( #foreach ( $field in $inheritedFields ) - ${field.name}, + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}${sep} #end + #if ( $locationTracking ) locations, location, - #foreach ( $field in $inheritedFields ) - #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) ${field.name}Location${sep} + #end #end ); #end #if ( $class == $root ) this.modelEncoding = modelEncoding; #end - #foreach ( $field in $class.allFields ) + #foreach ( $field in $class.getFields($version) ) #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) this.${field.name} = ImmutableCollections.copy( ${field.name} ); #else this.${field.name} = ${field.name}; #end #end - #if ( ! $class.superClass ) + #if ( $locationTracking ) + #if ( ! $class.superClass ) this.locations = ImmutableCollections.copy( locations ); this.location = location; - #end - #foreach ( $field in $class.allFields ) + #end + #foreach ( $field in $class.getFields($version) ) this.${field.name}Location = ${field.name}Location; + #end #end } @@ -228,7 +225,7 @@ public class ${class.name} } #end - #foreach ( $field in $class.allFields ) + #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" ) @@ -251,6 +248,7 @@ public class ${class.name} } #end + #if ( $locationTracking ) /** * Gets the location of the specified field in the input source. */ @@ -260,23 +258,24 @@ public class ${class.name} { switch ( ( String ) key ) { - #if ( ! $class.superClass ) + #if ( ! $class.superClass ) case "": return location; - #end - #foreach ( $field in $class.allFields ) + #end + #foreach ( $field in $class.getFields($version) ) case "${field.name}": return ${field.name}Location; - #end + #end } } - #if ( $class.superClass ) + #if ( $class.superClass ) return super.getLocation( key ); - #else + #else return locations != null ? locations.get( key ) : null; - #end + #end } + #end /** * Creates a new builder with this object as the basis. */ @@ -374,7 +373,7 @@ public class ${class.name} #if ( $class == $root ) String modelEncoding; #end - #foreach ( $field in $class.allFields ) + #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) #if ( $type.startsWith("List<") ) #set ( $type = ${type.replace('List<','Collection<')} ) @@ -387,7 +386,7 @@ public class ${class.name} ${type} ${field.name}; #end #end - #if ( ! $class.superClass ) + #if ( ! $class.superClass && $locationTracking ) Map locations; #end @@ -398,7 +397,7 @@ public class ${class.name} #end if ( withDefaults ) { - #foreach ( $field in $class.allFields ) + #foreach ( $field in $class.getFields($version) ) #if ( $field.defaultValue ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) #if ( $field.type == "String" ) @@ -418,7 +417,7 @@ public class ${class.name} #end if ( forceCopy ) { - #foreach ( $field in $class.allFields ) + #foreach ( $field in $class.getFields($version) ) this.${field.name} = base.${field.name}; #end } @@ -451,6 +450,7 @@ public class ${class.name} #end + #if ( $locationTracking ) @Nonnull public Builder location( Object key, InputLocation location ) { @@ -465,6 +465,7 @@ public class ${class.name} return this; } + #end @Nonnull public ${class.name} build() { @@ -476,31 +477,32 @@ public class ${class.name} { return base; } + #if ( $locationTracking ) Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); InputLocation location = locations.remove( "" ); - #foreach ( $field in $allFields ) + #foreach ( $field in $allFields ) InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end #end return new ${class.name}( #if ( $class == $root ) modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), #end #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) #if ( $field.type == "boolean" || $field.type == "int" ) - ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} ), + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} #else - ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ), + ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} #end #end + #if ( $locationTracking ) locations, location != null ? location : ( base != null ? base.location : null ), - #foreach ( $field in $allFields ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end #end ); } diff --git a/api/maven-api-settings/pom.xml b/api/maven-api-settings/pom.xml index 617f6f2eb004..e6b3c9c0ebbc 100644 --- a/api/maven-api-settings/pom.xml +++ b/api/maven-api-settings/pom.xml @@ -77,7 +77,7 @@ under the License. - basePackage=org.apache.maven.api.settings + packageModelV4=org.apache.maven.api.settings diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ImmutableCollections.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ImmutableCollections.java new file mode 100644 index 000000000000..850e0ef6659a --- /dev/null +++ b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ImmutableCollections.java @@ -0,0 +1,738 @@ +package org.apache.maven.api.settings; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); + default: + return new ListN<>( collection ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map instanceof AbstractImmutableMap ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return new MapN<>( map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static Map emptyMap() + { + return ( Map ) EMPTY_MAP; + } + + static Map singletonMap( K key, V value ) + { + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + private List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + + private static class ListN extends AbstractImmutableList + { + private final Object[] elements; + + private ListN( Collection elements ) + { + this.elements = elements.toArray(); + } + + @SuppressWarnings( "unchecked" ) + @Override + public E get( int index ) + { + return ( E ) elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0 ) + { + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } + if ( toIndex > size() ) + { + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } + if ( fromIndex > toIndex ) + { + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + private class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + private SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + private class Itr implements ListIterator + { + int index; + + private Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java b/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java deleted file mode 100644 index 49cdfebf5dd3..000000000000 --- a/api/maven-api-settings/src/main/java/org/apache/maven/api/settings/ROProperties.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.apache.maven.api.settings; - -/* - * 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. - */ - -import java.util.Map; -import java.util.Properties; -import java.util.function.BiFunction; -import java.util.function.Function; - -class ROProperties extends Properties -{ - ROProperties( Properties props ) - { - super(); - if ( props != null ) - { - // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException - for ( Map.Entry e : props.entrySet() ) - { - super.put( e.getKey(), e.getValue() ); - } - } - } - - @Override - public Object put( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object remove( Object key ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void putAll( Map t ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void clear() - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void replaceAll( BiFunction function ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object putIfAbsent( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public boolean remove( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public boolean replace( Object key, Object oldValue, Object newValue ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object replace( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object computeIfAbsent( Object key, Function mappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object computeIfPresent( Object key, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object compute( Object key, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object merge( Object key, Object value, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - -} diff --git a/api/maven-api-settings/src/main/mdo/common.vm b/api/maven-api-settings/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/api/maven-api-settings/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm index 55e3c29e9411..c981c2bd5138 100644 --- a/api/maven-api-settings/src/main/mdo/model.vm +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $package = "${basePackage}" ) -#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#parse ( "src/main/mdo/common.vm" ) # +#set ( $package = "${packageModelV4}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) #set ( $allFields = [] ) @@ -29,7 +30,8 @@ #end #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) #end -#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) @@ -38,10 +40,14 @@ #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) #foreach ( $field in $allFields ) #if ( $field.type == "java.util.List" ) #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) #set ( $dummy = $imports.add( "java.util.List" ) ) #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) #elseif ( $field.type == "DOM" ) @@ -79,48 +85,92 @@ // ============================================================== package ${package}; - #foreach ( $imp in $imports ) + #foreach ( $imp in $imports ) import $imp; - #end + #end -@Generated +/** + #foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ +@Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) extends ${class.superClass} #end + #if ( $locationTracking ) + implements Serializable, InputLocationTracker + #else implements Serializable + #end { #if ( $class == $root ) final String modelEncoding; #end #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ final ${type} $field.name; #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + /** Location of the xml element for this object. */ + final InputLocation location; + #end + #foreach ( $field in $class.getFields($version) ) + /** Location of the xml element for the field ${field.name}. */ + final InputLocation ${field.name}Location; + #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + #end + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ ${class.name}( #if ( $class == $root ) String modelEncoding, #end #foreach ( $field in $allFields ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name${sep} + #end + #if ( $locationTracking ) + Map locations, + InputLocation location, + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + InputLocation ${field.name}Location${sep} #end - ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} $field.name${sep} #end ) { #if ( $class.superClass ) super( #foreach ( $field in $inheritedFields ) - #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) ${field.name}${sep} + #end + #if ( $locationTracking ) + locations, + location, + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}Location${sep} + #end #end ); #end @@ -128,7 +178,20 @@ public class ${class.name} this.modelEncoding = modelEncoding; #end #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else this.${field.name} = ${field.name}; + #end + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + this.locations = ImmutableCollections.copy( locations ); + this.location = location; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name}Location = ${field.name}Location; + #end #end } @@ -170,6 +233,12 @@ public class ${class.name} #else #set ( $pfx = "get" ) #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end @@ -179,45 +248,122 @@ public class ${class.name} } #end + #if ( $locationTracking ) + /** + * Gets the location of the specified field in the input source. + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.getFields($version) ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #end + /** + * Creates a new builder with this object as the basis. + */ + @Nonnull + public Builder with() + { + return newBuilder( this ); + } #foreach ( $field in $allFields ) #set ( $cap = $Helper.capitalise( $field.name ) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + /** Creates a new ${class.name} instance using the specified ${field.name}. */ + @Nonnull public ${class.name} with${cap}( $type $field.name ) { - return newBuilder( this ).${field.name}( $field.name ).build(); + return with().${field.name}( $field.name ).build(); } #end + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ + @Nonnull public static ${class.name} newInstance() { return newInstance( true ); } + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ + @Nonnull public static ${class.name} newInstance( boolean withDefaults ) { return newBuilder( withDefaults ).build(); } + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ + @Nonnull public static Builder newBuilder() { return newBuilder( true ); } + /** + * Creates a new ${class.name} builder instance using default values or not. + */ + @Nonnull public static Builder newBuilder( boolean withDefaults ) { return new Builder( withDefaults ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ + @Nonnull public static Builder newBuilder( ${class.name} from ) { return newBuilder( from, false ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ + @Nonnull public static Builder newBuilder( ${class.name} from, boolean forceCopy ) { return new Builder( from, forceCopy ); } + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ + @NotThreadSafe public static class Builder #if ( $class.superClass ) extends ${class.superClass}.Builder @@ -229,6 +375,9 @@ public class ${class.name} #end #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end #if ( $type == 'boolean' ) Boolean ${field.name}; #elseif ( $type == 'int' ) @@ -236,6 +385,9 @@ public class ${class.name} #else ${type} ${field.name}; #end + #end + #if ( ! $class.superClass && $locationTracking ) + Map locations; #end Builder( boolean withDefaults ) @@ -276,6 +428,7 @@ public class ${class.name} } #if ( $class == $root ) + @Nonnull public Builder modelEncoding( String modelEncoding ) { this.modelEncoding = modelEncoding; @@ -285,6 +438,10 @@ public class ${class.name} #end #foreach ( $field in $allFields ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + @Nonnull public Builder ${field.name}( ${type} ${field.name} ) { this.${field.name} = ${field.name}; @@ -293,6 +450,23 @@ public class ${class.name} #end + #if ( $locationTracking ) + @Nonnull + public Builder location( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + } + return this; + } + + #end + @Nonnull public ${class.name} build() { if ( base != null @@ -303,31 +477,38 @@ public class ${class.name} { return base; } + #if ( $locationTracking ) + Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); + InputLocation location = locations.remove( "" ); + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end + #end return new ${class.name}( #if ( $class == $root ) modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), #end #foreach ( $field in $allFields ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end - #if ( $field.type == "java.util.List" ) - ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() )${sep} - #elseif ( $field.type == "java.util.Properties" ) - new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) )${sep} - #elseif ( $field.type == "boolean" || $field.type == "int" ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #if ( $field.type == "boolean" || $field.type == "int" ) ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} #else ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} #end + #end + #if ( $locationTracking ) + locations, + location != null ? location : ( base != null ? base.location : null ), + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end #end ); } } - #foreach ( $cs in $class.allCodeSegments ) + #foreach ( $cs in $class.getCodeSegments($version) ) $cs.code #end } diff --git a/api/maven-api-toolchain/pom.xml b/api/maven-api-toolchain/pom.xml index 4107d3ef4d85..cba137cf612f 100644 --- a/api/maven-api-toolchain/pom.xml +++ b/api/maven-api-toolchain/pom.xml @@ -78,7 +78,7 @@ under the License. - basePackage=org.apache.maven.api.toolchain + packageModelV4=org.apache.maven.api.toolchain diff --git a/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ImmutableCollections.java b/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ImmutableCollections.java new file mode 100644 index 000000000000..934a40331681 --- /dev/null +++ b/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ImmutableCollections.java @@ -0,0 +1,738 @@ +package org.apache.maven.api.toolchain; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); + default: + return new ListN<>( collection ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map instanceof AbstractImmutableMap ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return new MapN<>( map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static Map emptyMap() + { + return ( Map ) EMPTY_MAP; + } + + static Map singletonMap( K key, V value ) + { + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + private List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + + private static class ListN extends AbstractImmutableList + { + private final Object[] elements; + + private ListN( Collection elements ) + { + this.elements = elements.toArray(); + } + + @SuppressWarnings( "unchecked" ) + @Override + public E get( int index ) + { + return ( E ) elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0 ) + { + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } + if ( toIndex > size() ) + { + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } + if ( fromIndex > toIndex ) + { + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + private class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + private SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + private class Itr implements ListIterator + { + int index; + + private Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java b/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java deleted file mode 100644 index 9ae6c6d4c82b..000000000000 --- a/api/maven-api-toolchain/src/main/java/org/apache/maven/api/toolchain/ROProperties.java +++ /dev/null @@ -1,120 +0,0 @@ -package org.apache.maven.api.toolchain; - -/* - * 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. - */ - -import java.util.Map; -import java.util.Properties; -import java.util.function.BiFunction; -import java.util.function.Function; - -class ROProperties extends Properties -{ - ROProperties( Properties props ) - { - super(); - if ( props != null ) - { - // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException - for ( Map.Entry e : props.entrySet() ) - { - super.put( e.getKey(), e.getValue() ); - } - } - } - - @Override - public Object put( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object remove( Object key ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void putAll( Map t ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void clear() - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public void replaceAll( BiFunction function ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object putIfAbsent( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public boolean remove( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public boolean replace( Object key, Object oldValue, Object newValue ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object replace( Object key, Object value ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object computeIfAbsent( Object key, Function mappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object computeIfPresent( Object key, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object compute( Object key, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - - @Override - public Object merge( Object key, Object value, BiFunction remappingFunction ) - { - throw new UnsupportedOperationException( "Properties are read-only" ); - } - -} diff --git a/api/maven-api-toolchain/src/main/mdo/common.vm b/api/maven-api-toolchain/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/api/maven-api-toolchain/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm index 5d47aeca9a85..c981c2bd5138 100644 --- a/api/maven-api-toolchain/src/main/mdo/model.vm +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $package = "${basePackage}" ) -#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#parse ( "src/main/mdo/common.vm" ) # +#set ( $package = "${packageModelV4}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) #set ( $allFields = [] ) @@ -29,7 +30,8 @@ #end #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) #end -#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) @@ -38,10 +40,14 @@ #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) #foreach ( $field in $allFields ) #if ( $field.type == "java.util.List" ) #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) #set ( $dummy = $imports.add( "java.util.List" ) ) #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) #elseif ( $field.type == "DOM" ) @@ -79,49 +85,92 @@ // ============================================================== package ${package}; - #foreach ( $imp in $imports ) + #foreach ( $imp in $imports ) import $imp; - #end + #end -@Generated +/** + #foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ +@Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) extends ${class.superClass} #end + #if ( $locationTracking ) + implements Serializable, InputLocationTracker + #else implements Serializable + #end { #if ( $class == $root ) final String modelEncoding; #end #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ final ${type} $field.name; #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + /** Location of the xml element for this object. */ + final InputLocation location; + #end + #foreach ( $field in $class.getFields($version) ) + /** Location of the xml element for the field ${field.name}. */ + final InputLocation ${field.name}Location; + #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + #end + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ ${class.name}( #if ( $class == $root ) String modelEncoding, #end #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name${sep} + #end + #if ( $locationTracking ) + Map locations, + InputLocation location, + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + InputLocation ${field.name}Location${sep} #end - ${type} $field.name${sep} #end ) { #if ( $class.superClass ) super( #foreach ( $field in $inheritedFields ) - #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) ${field.name}${sep} + #end + #if ( $locationTracking ) + locations, + location, + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}Location${sep} + #end #end ); #end @@ -129,7 +178,20 @@ public class ${class.name} this.modelEncoding = modelEncoding; #end #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else this.${field.name} = ${field.name}; + #end + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + this.locations = ImmutableCollections.copy( locations ); + this.location = location; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name}Location = ${field.name}Location; + #end #end } @@ -171,6 +233,12 @@ public class ${class.name} #else #set ( $pfx = "get" ) #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end @@ -180,45 +248,122 @@ public class ${class.name} } #end + #if ( $locationTracking ) + /** + * Gets the location of the specified field in the input source. + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.getFields($version) ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #end + /** + * Creates a new builder with this object as the basis. + */ + @Nonnull + public Builder with() + { + return newBuilder( this ); + } #foreach ( $field in $allFields ) #set ( $cap = $Helper.capitalise( $field.name ) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + /** Creates a new ${class.name} instance using the specified ${field.name}. */ + @Nonnull public ${class.name} with${cap}( $type $field.name ) { - return newBuilder( this ).${field.name}( $field.name ).build(); + return with().${field.name}( $field.name ).build(); } #end + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ + @Nonnull public static ${class.name} newInstance() { return newInstance( true ); } + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ + @Nonnull public static ${class.name} newInstance( boolean withDefaults ) { return newBuilder( withDefaults ).build(); } + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ + @Nonnull public static Builder newBuilder() { return newBuilder( true ); } + /** + * Creates a new ${class.name} builder instance using default values or not. + */ + @Nonnull public static Builder newBuilder( boolean withDefaults ) { return new Builder( withDefaults ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ + @Nonnull public static Builder newBuilder( ${class.name} from ) { return newBuilder( from, false ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ + @Nonnull public static Builder newBuilder( ${class.name} from, boolean forceCopy ) { return new Builder( from, forceCopy ); } + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ + @NotThreadSafe public static class Builder #if ( $class.superClass ) extends ${class.superClass}.Builder @@ -230,6 +375,9 @@ public class ${class.name} #end #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end #if ( $type == 'boolean' ) Boolean ${field.name}; #elseif ( $type == 'int' ) @@ -237,6 +385,9 @@ public class ${class.name} #else ${type} ${field.name}; #end + #end + #if ( ! $class.superClass && $locationTracking ) + Map locations; #end Builder( boolean withDefaults ) @@ -277,6 +428,7 @@ public class ${class.name} } #if ( $class == $root ) + @Nonnull public Builder modelEncoding( String modelEncoding ) { this.modelEncoding = modelEncoding; @@ -286,6 +438,10 @@ public class ${class.name} #end #foreach ( $field in $allFields ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + @Nonnull public Builder ${field.name}( ${type} ${field.name} ) { this.${field.name} = ${field.name}; @@ -294,6 +450,23 @@ public class ${class.name} #end + #if ( $locationTracking ) + @Nonnull + public Builder location( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + } + return this; + } + + #end + @Nonnull public ${class.name} build() { if ( base != null @@ -304,31 +477,38 @@ public class ${class.name} { return base; } + #if ( $locationTracking ) + Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); + InputLocation location = locations.remove( "" ); + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end + #end return new ${class.name}( #if ( $class == $root ) modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), #end #foreach ( $field in $allFields ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end - #if ( $field.type == "java.util.List" ) - ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() )${sep} - #elseif ( $field.type == "java.util.Properties" ) - new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) )${sep} - #elseif ( $field.type == "boolean" || $field.type == "int" ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #if ( $field.type == "boolean" || $field.type == "int" ) ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} #else ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} #end + #end + #if ( $locationTracking ) + locations, + location != null ? location : ( base != null ? base.location : null ), + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end #end ); } } - #foreach ( $cs in $class.allCodeSegments ) + #foreach ( $cs in $class.getCodeSegments($version) ) $cs.code #end } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 87f2bfef3a9d..2959361273b2 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -87,7 +87,7 @@ import org.apache.maven.model.resolution.UnresolvableModelException; import org.apache.maven.model.resolution.WorkspaceModelResolver; import org.apache.maven.model.superpom.SuperPomProvider; -import org.apache.maven.model.v4.ModelMerger; +import org.apache.maven.model.v4.MavenMerger; import org.apache.maven.model.validation.ModelValidator; import org.codehaus.plexus.interpolation.InterpolationException; import org.codehaus.plexus.interpolation.MapBasedValueSource; @@ -106,7 +106,7 @@ public class DefaultModelBuilder implements ModelBuilder { - private final ModelMerger modelMerger = new FileToRawModelMerger(); + private final MavenMerger mavenMerger = new FileToRawModelMerger(); private final ModelProcessor modelProcessor; private final ModelValidator modelValidator; @@ -993,7 +993,7 @@ private Model readRawModel( ModelBuildingRequest request, DefaultModelProblemCol // rawModel with locationTrackers, required for proper feedback during validations // Apply enriched data - rawModel = modelMerger.merge( rawModel, transformedFileModel, false, null ); + rawModel = mavenMerger.merge( rawModel, transformedFileModel, false, null ); } catch ( IOException e ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java index 5918dbc415ed..2609c91efd12 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FileToRawModelMerger.java @@ -35,7 +35,7 @@ import org.apache.maven.api.model.Profile; import org.apache.maven.api.model.ReportPlugin; import org.apache.maven.api.model.Reporting; -import org.apache.maven.model.v4.ModelMerger; +import org.apache.maven.model.v4.MavenMerger; /** * As long as Maven controls the BuildPomXMLFilter, the entities that need merging are known. @@ -44,7 +44,7 @@ * @author Robert Scholte * @since 4.0.0 */ -class FileToRawModelMerger extends ModelMerger +class FileToRawModelMerger extends MavenMerger { @Override diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java index 4e53db546f99..c77ac70f7f65 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/StringVisitorModelInterpolator.java @@ -34,7 +34,7 @@ import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblemCollectorRequest; -import org.apache.maven.model.v4.ModelTransformer; +import org.apache.maven.model.v4.MavenTransformer; import org.apache.maven.model.path.PathTranslator; import org.apache.maven.model.path.UrlNormalizer; import org.codehaus.plexus.interpolation.InterpolationException; @@ -75,7 +75,7 @@ public Model interpolateModel( Model model, File projectDir, ModelBuildingReques InnerInterpolator innerInterpolator = createInterpolator( valueSources, postProcessors, problems ); - return new ModelTransformer( innerInterpolator::interpolate ).visit( model ); + return new MavenTransformer( innerInterpolator::interpolate ).visit( model ); } private InnerInterpolator createInterpolator( List valueSources, 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 a218c54c3715..f025a3278be5 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 @@ -46,7 +46,7 @@ import org.apache.maven.api.model.RepositoryBase; import org.apache.maven.api.model.Scm; import org.apache.maven.api.model.Site; -import org.apache.maven.model.v4.ModelMerger; +import org.apache.maven.model.v4.MavenMerger; import org.codehaus.plexus.util.StringUtils; /** @@ -56,7 +56,7 @@ * @author Benjamin Bentmann */ public class MavenModelMerger - extends ModelMerger + extends MavenMerger { /** diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java index b3755d9b6cb4..dee13836af5a 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/FileToRawModelMergerTest.java @@ -26,7 +26,7 @@ import java.util.stream.Collectors; import java.util.stream.Stream; -import org.apache.maven.model.v4.ModelMerger; +import org.apache.maven.model.v4.MavenMerger; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -42,7 +42,7 @@ public class FileToRawModelMergerTest public void testOverriddenMergeMethods() { List methodNames = - Stream.of( ModelMerger.class.getDeclaredMethods() ) + Stream.of( MavenMerger.class.getDeclaredMethods() ) .filter( m -> m.getName().startsWith( "merge" ) ) .filter( m -> { diff --git a/maven-model/src/main/mdo/common.vm b/maven-model/src/main/mdo/common.vm new file mode 100644 index 000000000000..3c3f29cf7a27 --- /dev/null +++ b/maven-model/src/main/mdo/common.vm @@ -0,0 +1,31 @@ +#* + Licensed to the Apache Software Foundation (ASF) under one + or more contributor license agreements. See the NOTICE file + distributed with this work for additional information + regarding copyright ownership. The ASF licenses this file + to you under the Apache License, Version 2.0 (the + "License"); you may not use this file except in compliance + with the License. You may obtain a copy of the License at + + http://www.apache.org/licenses/LICENSE-2.0 + + Unless required by applicable law or agreed to in writing, + software distributed under the License is distributed on an + "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + KIND, either express or implied. See the License for the + specific language governing permissions and limitations + under the License. +*# +# +## +## The following loop code is required in order to change the type of the +## pomFile attribute to a java.nio.file.Path. Modello does not support this +## type and loading a model with such a type would fail the modello validation. +## +#foreach ( $field in $model.getClass("Model", $version).allFields ) + #if ( $field.name == "pomFile" ) + #set ( $dummy = $field.setType("java.nio.file.Path") ) + #end +#end +#set ( $locationTracking = true ) +# \ No newline at end of file diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm index bb6954ba38aa..8358f306b080 100644 --- a/maven-model/src/main/mdo/merger.vm +++ b/maven-model/src/main/mdo/merger.vm @@ -16,15 +16,12 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) -#set ( $className = "ModelMerger" ) +#set ( $className = "${model.name}Merger" ) # -#foreach ( $field in $model.getClass("Model", $version).allFields ) - #if ( $field.name == "pomFile" ) - #set ( $dummy = $field.setType("java.nio.file.Path") ) - #end -#end +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== @@ -69,7 +66,7 @@ public class ${className} * @param hints A set of key-value pairs that customized merger implementations can use to carry domain-specific * information along, may be null. */ - public Model merge( Model target, Model source, boolean sourceDominant, Map hints ) + public ${root.name} merge( ${root.name} target, ${root.name} source, boolean sourceDominant, Map hints ) { Objects.requireNonNull( target, "target cannot be null" ); if ( source == null ) @@ -81,7 +78,7 @@ public class ${className} { context.putAll( hints ); } - return mergeModel( target, source, sourceDominant, context ); + return merge${root.name}( target, source, sourceDominant, context ); } #foreach ( $class in $model.allClasses ) @@ -89,7 +86,7 @@ public class ${className} #set ( $ancestors = $Helper.ancestors( $class ) ) #set ( $allFields = [] ) #foreach ( $cl in $ancestors ) - #set ( $dummy = $allFields.addAll( $cl.allFields ) ) + #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) #end protected ${class.name} merge${class.name}( ${class.name} target, ${class.name} source, boolean sourceDominant, Map context ) { @@ -103,7 +100,7 @@ public class ${className} #if ( $class.superClass ) merge${class.superClass}( builder, target ,source, sourceDominant, context ); #end - #foreach ( $field in $class.allFields ) + #foreach ( $field in $class.getFields($version) ) merge${field.modelClass.name}_${Helper.capitalise($field.name)}( builder, target, source, sourceDominant, context ); #end } @@ -118,7 +115,9 @@ public class ${className} if ( src != null && ( sourceDominant || tgt == null ) ) { builder.${field.name}( src ); + #if ( $locationTracking ) builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); @@ -130,7 +129,9 @@ public class ${className} if ( tgt == null ) { builder.${field.name}( src ); + #if ( $locationTracking ) builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else { @@ -138,7 +139,9 @@ public class ${className} merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); builder.${field.name}( merged ); + #if ( $locationTracking ) builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "1" ) @@ -154,12 +157,16 @@ public class ${className} if ( merged == src ) { builder.${field.name}( merged ); + #if ( $locationTracking ) builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else if ( merged != tgt ) { builder.${field.name}( merged ); + #if ( $locationTracking ) builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "*" ) diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index edf5b3437c02..04d60d427044 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageModelV3}" ) # diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm index e2931925a472..47d1373d0da4 100644 --- a/maven-model/src/main/mdo/reader-ex.vm +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) -#set ( $className = "MavenXpp3ReaderEx" ) +#set ( $className = "${model.name}Xpp3ReaderEx" ) # #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm index a1a52b121856..fd0bb50b26e0 100644 --- a/maven-model/src/main/mdo/reader.vm +++ b/maven-model/src/main/mdo/reader.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) -#set ( $className = "MavenXpp3Reader" ) +#set ( $className = "${model.name}Xpp3Reader" ) # #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm index 882d639aaa9b..f309df1a3985 100644 --- a/maven-model/src/main/mdo/transformer.vm +++ b/maven-model/src/main/mdo/transformer.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) -#set ( $className = "ModelTransformer" ) +#set ( $className = "${model.name}Transformer" ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== diff --git a/maven-model/src/main/mdo/writer-ex.vm b/maven-model/src/main/mdo/writer-ex.vm index 0ffb6c746db8..cae13506df70 100644 --- a/maven-model/src/main/mdo/writer-ex.vm +++ b/maven-model/src/main/mdo/writer-ex.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) -#set ( $className = "MavenXpp3WriterEx" ) +#set ( $className = "${model.name}Xpp3WriterEx" ) # #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) diff --git a/maven-model/src/main/mdo/writer.vm b/maven-model/src/main/mdo/writer.vm index bcf705f89c85..e2740f45a4d3 100644 --- a/maven-model/src/main/mdo/writer.vm +++ b/maven-model/src/main/mdo/writer.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) -#set ( $className = "MavenXpp3Writer" ) +#set ( $className = "${model.name}Xpp3Writer" ) # #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) diff --git a/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java b/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java similarity index 96% rename from maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java rename to maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java index 69ebf66cb7bf..02b3a32fa2b3 100644 --- a/maven-model/src/test/java/org/apache/maven/model/merge/ModelMergerTest.java +++ b/maven-model/src/test/java/org/apache/maven/model/merge/MavenMergerTest.java @@ -24,7 +24,7 @@ import org.apache.maven.api.model.Contributor; import org.apache.maven.api.model.Dependency; import org.apache.maven.api.model.Model; -import org.apache.maven.model.v4.ModelMerger; +import org.apache.maven.model.v4.MavenMerger; import org.junit.jupiter.api.Test; import static org.hamcrest.MatcherAssert.assertThat; @@ -32,14 +32,14 @@ import static org.hamcrest.Matchers.is; /** - * ModelMerger is based on same instances, subclasses should override KeyComputer per type + * MavenMerger is based on same instances, subclasses should override KeyComputer per type * * @author Robert Scholte * */ -public class ModelMergerTest +public class MavenMergerTest { - private ModelMerger modelMerger = new ModelMerger(); + private MavenMerger mavenMerger = new MavenMerger(); @Test public void mergeArtifactId() @@ -48,10 +48,10 @@ public void mergeArtifactId() Model source = Model.newBuilder().artifactId( "SOURCE" ).build(); - Model merged = modelMerger.merge( target, source, true, null ); + Model merged = mavenMerger.merge( target, source, true, null ); assertThat( merged.getArtifactId(), is( "SOURCE" ) ); - merged = modelMerger.merge( target, source, false, null ); + merged = mavenMerger.merge( target, source, false, null ); assertThat( merged.getArtifactId(), is( "TARGET" ) ); } @@ -64,7 +64,7 @@ public void mergeSameContributors() Model source = Model.newBuilder().contributors( Arrays.asList( contributor ) ).build(); - Model merged = modelMerger.merge( target, source, true, null ); + Model merged = mavenMerger.merge( target, source, true, null ); assertThat( merged.getContributors(), contains( contributor ) ); } @@ -78,7 +78,7 @@ public void mergeSameDependencies() Model source = Model.newBuilder().dependencies( Arrays.asList( dependency ) ).build(); - Model merged = modelMerger.merge( target, source, true, null ); + Model merged = mavenMerger.merge( target, source, true, null ); assertThat( merged.getDependencies(), contains( dependency ) ); } @@ -420,7 +420,7 @@ public void testMergedModelSerialization() throws Exception { source.setLicenses(new ArrayList()); source.getLicenses().add(lic2); - new ModelMerger().mergeModel(target, source, false, null); + new MavenMerger().mergeModel(target, source, false, null); ByteArrayOutputStream baos = new ByteArrayOutputStream(); ObjectOutputStream oos = new ObjectOutputStream(baos); diff --git a/maven-plugin-api/pom.xml b/maven-plugin-api/pom.xml index 057014307c82..828eaf49c18d 100644 --- a/maven-plugin-api/pom.xml +++ b/maven-plugin-api/pom.xml @@ -113,6 +113,11 @@ under the License. + + packageModelV3=org.apache.maven.plugin.lifecycle + packageModelV4=org.apache.maven.plugin.lifecycle + packageToolV4=org.apache.maven.plugin.lifecycle.io.xpp3 + diff --git a/maven-plugin-api/src/main/java/org/apache/maven/plugin/lifecycle/ImmutableCollections.java b/maven-plugin-api/src/main/java/org/apache/maven/plugin/lifecycle/ImmutableCollections.java new file mode 100644 index 000000000000..4479e411361d --- /dev/null +++ b/maven-plugin-api/src/main/java/org/apache/maven/plugin/lifecycle/ImmutableCollections.java @@ -0,0 +1,738 @@ +package org.apache.maven.plugin.lifecycle; + +/* + * 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. + */ + +import java.util.AbstractList; +import java.util.AbstractMap; +import java.util.AbstractSet; +import java.util.Collection; +import java.util.Comparator; +import java.util.Iterator; +import java.util.List; +import java.util.ListIterator; +import java.util.Map; +import java.util.NoSuchElementException; +import java.util.Properties; +import java.util.RandomAccess; +import java.util.Set; +import java.util.function.BiFunction; +import java.util.function.Function; +import java.util.function.Predicate; +import java.util.function.UnaryOperator; + +class ImmutableCollections +{ + + private static final List EMPTY_LIST = new AbstractImmutableList() + { + @Override + public Object get( int index ) + { + throw new IndexOutOfBoundsException(); + } + @Override + public int size() + { + return 0; + } + }; + + private static final Map EMPTY_MAP = new AbstractImmutableMap() + { + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + @Override + public boolean hasNext() + { + return false; + } + @Override + public Entry next() + { + throw new NoSuchElementException(); + } + }; + } + @Override + public int size() + { + return 0; + } + }; + } + }; + + static List copy( Collection collection ) + { + if ( collection == null ) + { + return emptyList(); + } + else if ( collection instanceof AbstractImmutableList ) + { + return ( List ) collection; + } + else + { + switch ( collection.size() ) + { + case 0: + return emptyList(); + case 1: + return singletonList( collection.iterator().next() ); + case 2: + Iterator it = collection.iterator(); + return new List2<>( it.next(), it.next() ); + default: + return new ListN<>( collection ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static List emptyList() + { + return ( List ) EMPTY_LIST; + } + + static List singletonList( E element ) + { + return new List1<>( element ); + } + + static Map copy( Map map ) + { + if ( map == null ) + { + return emptyMap(); + } + else if ( map instanceof AbstractImmutableMap ) + { + return map; + } + else + { + switch ( map.size() ) + { + case 0: + return emptyMap(); + case 1: + Map.Entry entry = map.entrySet().iterator().next(); + return singletonMap( entry.getKey(), entry.getValue() ); + default: + return new MapN<>( map ); + } + } + } + + @SuppressWarnings( "unchecked" ) + static Map emptyMap() + { + return ( Map ) EMPTY_MAP; + } + + static Map singletonMap( K key, V value ) + { + return new Map1<>( key, value ); + } + + static Properties copy( Properties properties ) + { + if ( properties instanceof ROProperties ) + { + return properties; + } + return new ROProperties( properties ); + } + + private static class List1 extends AbstractImmutableList + { + private final E element; + + private List1( E element ) + { + this.element = element; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 1; + } + } + + private static class List2 extends AbstractImmutableList + { + private final E element1; + private final E element2; + + private List2( E element1, E element2 ) + { + this.element1 = element1; + this.element2 = element2; + } + + @Override + public E get( int index ) + { + if ( index == 0 ) + { + return element1; + } + else if ( index == 1 ) + { + return element2; + } + throw outOfBounds( index ); + } + + @Override + public int size() + { + return 2; + } + } + + private static class ListN extends AbstractImmutableList + { + private final Object[] elements; + + private ListN( Collection elements ) + { + this.elements = elements.toArray(); + } + + @SuppressWarnings( "unchecked" ) + @Override + public E get( int index ) + { + return ( E ) elements[ index ]; + } + + @Override + public int size() + { + return elements.length; + } + } + + private abstract static class AbstractImmutableList extends AbstractList implements RandomAccess + { + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean addAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + + @Override + public void replaceAll( UnaryOperator operator ) + { + throw uoe(); + } + + @Override + public void sort( Comparator c ) + { + throw uoe(); + } + + @Override + public Iterator iterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator() + { + return new Itr( 0 ); + } + + @Override + public ListIterator listIterator( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return new Itr( index ); + } + + @Override + public List subList( int fromIndex, int toIndex ) + { + if ( fromIndex < 0 ) + { + throw new IndexOutOfBoundsException( "fromIndex = " + fromIndex ); + } + if ( toIndex > size() ) + { + throw new IndexOutOfBoundsException( "toIndex = " + toIndex ); + } + if ( fromIndex > toIndex ) + { + throw new IllegalArgumentException( "fromIndex(" + fromIndex + ") > toIndex(" + toIndex + ")" ); + } + return new SubList( fromIndex, toIndex ); + } + + protected IndexOutOfBoundsException outOfBounds( int index ) + { + return new IndexOutOfBoundsException( "Index: " + index + ", Size: " + size() ); + } + + private class SubList extends AbstractImmutableList + { + private final int fromIndex; + private final int toIndex; + + private SubList( int fromIndex, int toIndex ) + { + this.fromIndex = fromIndex; + this.toIndex = toIndex; + } + + @Override + public E get( int index ) + { + if ( index < 0 || index > size() ) + { + throw outOfBounds( index ); + } + return AbstractImmutableList.this.get( fromIndex + index ); + } + + @Override + public int size() + { + return toIndex - fromIndex; + } + } + + private class Itr implements ListIterator + { + int index; + + private Itr( int index ) + { + this.index = index; + } + + @Override + public boolean hasNext() + { + return index < size(); + } + + @Override + public E next() + { + return get( index++ ); + } + + @Override + public boolean hasPrevious() + { + return index > 0; + } + + @Override + public E previous() + { + return get( --index ); + } + + @Override + public int nextIndex() + { + return index; + } + + @Override + public int previousIndex() + { + return index - 1; + } + + @Override + public void remove() + { + throw uoe(); + } + + @Override + public void set( E e ) + { + throw uoe(); + } + + @Override + public void add( E e ) + { + throw uoe(); + } + } + } + + private static class ROProperties extends Properties + { + private ROProperties( Properties props ) + { + super(); + if ( props != null ) + { + // Do not use super.putAll, as it may delegate to put which throws an UnsupportedOperationException + for ( Map.Entry e : props.entrySet() ) + { + super.put( e.getKey(), e.getValue() ); + } + } + } + + @Override + public Object put( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object remove( Object key ) + { + throw uoe(); + } + + @Override + public void putAll( Map t ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public Object putIfAbsent( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( Object key, Object oldValue, Object newValue ) + { + throw uoe(); + } + + @Override + public Object replace( Object key, Object value ) + { + throw uoe(); + } + + @Override + public Object computeIfAbsent( Object key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public Object computeIfPresent( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object compute( Object key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public Object merge( Object key, Object value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private static class Map1 extends AbstractImmutableMap + { + private final Entry entry; + + private Map1( K key, V value ) + { + this.entry = new SimpleImmutableEntry<>( key, value ); + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index == 0; + } + + @Override + public Entry next() + { + if ( index++ == 0 ) + { + return entry; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return 1; + } + }; + } + } + + private static class MapN extends AbstractImmutableMap + { + private final Object[] entries; + + private MapN( Map map ) + { + entries = map != null ? map.entrySet().toArray() : new Object[0]; + } + + @Override + public Set> entrySet() + { + return new AbstractImmutableSet>() + { + @Override + public Iterator> iterator() + { + return new Iterator>() + { + int index = 0; + @Override + public boolean hasNext() + { + return index < entries.length; + } + + @SuppressWarnings( "unchecked" ) + @Override + public Entry next() + { + if ( index < entries.length ) + { + return ( Entry ) entries[index++]; + } + throw new NoSuchElementException(); + } + }; + } + + @Override + public int size() + { + return entries.length; + } + }; + } + } + + private abstract static class AbstractImmutableMap extends AbstractMap + { + @Override + public void replaceAll( BiFunction function ) + { + throw uoe(); + } + + @Override + public V putIfAbsent( K key, V value ) + { + throw uoe(); + } + + @Override + public boolean remove( Object key, Object value ) + { + throw uoe(); + } + + @Override + public boolean replace( K key, V oldValue, V newValue ) + { + throw uoe(); + } + + @Override + public V replace( K key, V value ) + { + throw uoe(); + } + + @Override + public V computeIfAbsent( K key, Function mappingFunction ) + { + throw uoe(); + } + + @Override + public V computeIfPresent( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V compute( K key, BiFunction remappingFunction ) + { + throw uoe(); + } + + @Override + public V merge( K key, V value, BiFunction remappingFunction ) + { + throw uoe(); + } + } + + private abstract static class AbstractImmutableSet extends AbstractSet + { + @Override + public boolean removeAll( Collection c ) + { + throw uoe(); + } + + @Override + public boolean add( E e ) + { + throw uoe(); + } + + @Override + public boolean remove( Object o ) + { + throw uoe(); + } + + @Override + public boolean retainAll( Collection c ) + { + throw uoe(); + } + + @Override + public void clear() + { + throw uoe(); + } + + @Override + public boolean removeIf( Predicate filter ) + { + throw uoe(); + } + } + + private static UnsupportedOperationException uoe() + { + return new UnsupportedOperationException(); + } + +} diff --git a/maven-plugin-api/src/main/mdo/common.vm b/maven-plugin-api/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/maven-plugin-api/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/maven-plugin-api/src/main/mdo/merger.vm b/maven-plugin-api/src/main/mdo/merger.vm index eb7070078fe8..8358f306b080 100644 --- a/maven-plugin-api/src/main/mdo/merger.vm +++ b/maven-plugin-api/src/main/mdo/merger.vm @@ -16,14 +16,12 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "${model.getDefault('package').getValue()}" ) -#set ( $package = "${basePackage}.merge" ) +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Merger" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) -#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) -#set ( $rootTag = $rootXml.tagName ) -#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) -#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== @@ -49,7 +47,7 @@ import java.util.stream.Collectors; import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.Name}; +import ${packageModelV4}.${class.Name}; #end @Generated @@ -117,6 +115,9 @@ public class ${className} if ( src != null && ( sourceDominant || tgt == null ) ) { builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); @@ -128,6 +129,9 @@ public class ${className} if ( tgt == null ) { builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else { @@ -135,6 +139,9 @@ public class ${className} merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "1" ) @@ -150,10 +157,16 @@ public class ${className} if ( merged == src ) { builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else if ( merged != tgt ) { builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "*" ) @@ -176,6 +189,16 @@ public class ${className} builder.configuration( tgt.merge( src ) ); } } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end diff --git a/maven-plugin-api/src/main/mdo/model.vm b/maven-plugin-api/src/main/mdo/model.vm index c925432023da..c981c2bd5138 100644 --- a/maven-plugin-api/src/main/mdo/model.vm +++ b/maven-plugin-api/src/main/mdo/model.vm @@ -16,9 +16,10 @@ specific language governing permissions and limitations under the License. *# -#set ( $package = "${model.getDefault('package').getValue()}" ) -#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) +#parse ( "src/main/mdo/common.vm" ) # +#set ( $package = "${packageModelV4}" ) +#set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #foreach ( $class in $model.allClasses ) #set ( $ancestors = $Helper.ancestors( $class ) ) #set ( $allFields = [] ) @@ -29,21 +30,29 @@ #end #set ( $dummy = $allFields.addAll( $cl.getFields($version) ) ) #end -#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${class.name}.java + #set ( $className = "${class.name}" ) +#MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java #if ( $class.name != "InputLocation" && $class.name != "InputSource" ) - #set ( $types = { "DOM": "org.apache.maven.api.xml.Dom" } ) + #set ( $types = { } ) #set ( $imports = $class.getClass().forName("java.util.TreeSet").newInstance() ) #set ( $dummy = $imports.add( "java.io.Serializable" ) ) #set ( $dummy = $imports.add( "java.util.Collections" ) ) #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.NotThreadSafe" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.ThreadSafe" ) ) #foreach ( $field in $allFields ) #if ( $field.type == "java.util.List" ) #set ( $dummy = $imports.add( "java.util.ArrayList" ) ) + #set ( $dummy = $imports.add( "java.util.Collection" ) ) #set ( $dummy = $imports.add( "java.util.List" ) ) #set ( $dummy = $types.put( $field, "List<" + $field.to + ">" ) ) + #elseif ( $field.type == "DOM" ) + #set ( $dummy = $imports.add( "org.apache.maven.api.xml.Dom" ) ) + #set ( $dummy = $types.put( $field, "Dom" ) ) #else #set ( $fieldType = ${types.getOrDefault($field.type,$field.type)} ) #set ( $idx = $fieldType.lastIndexOf('.') ) @@ -76,49 +85,92 @@ // ============================================================== package ${package}; - #foreach ( $imp in $imports ) + #foreach ( $imp in $imports ) import $imp; - #end + #end -@Generated +/** + #foreach ( $line in ${class.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ +@Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) extends ${class.superClass} #end + #if ( $locationTracking ) + implements Serializable, InputLocationTracker + #else implements Serializable + #end { #if ( $class == $root ) final String modelEncoding; #end #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + /** + #foreach ( $line in ${field.description.trim().split("\n")} ) + * ${line.trim()} + #end + */ final ${type} $field.name; #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + /** Location of the xml element for this object. */ + final InputLocation location; + #end + #foreach ( $field in $class.getFields($version) ) + /** Location of the xml element for the field ${field.name}. */ + final InputLocation ${field.name}Location; + #end + #if ( ! $class.superClass ) + /** Other locations */ + final Map locations; + #end + #end + /** + * Constructor for this class, package protected. + * @see Builder#build() + */ ${class.name}( #if ( $class == $root ) String modelEncoding, #end #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + $type $field.name${sep} + #end + #if ( $locationTracking ) + Map locations, + InputLocation location, + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + InputLocation ${field.name}Location${sep} #end - ${type} $field.name${sep} #end ) { #if ( $class.superClass ) super( #foreach ( $field in $inheritedFields ) - #if ( $field == ${inheritedFields[${inheritedFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end + #set ( $sep = "#if(${locationTracking}||$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) ${field.name}${sep} + #end + #if ( $locationTracking ) + locations, + location, + #foreach ( $field in $inheritedFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) + ${field.name}Location${sep} + #end #end ); #end @@ -126,7 +178,20 @@ public class ${class.name} this.modelEncoding = modelEncoding; #end #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" || $field.type == "java.util.Map" ) + this.${field.name} = ImmutableCollections.copy( ${field.name} ); + #else this.${field.name} = ${field.name}; + #end + #end + #if ( $locationTracking ) + #if ( ! $class.superClass ) + this.locations = ImmutableCollections.copy( locations ); + this.location = location; + #end + #foreach ( $field in $class.getFields($version) ) + this.${field.name}Location = ${field.name}Location; + #end #end } @@ -168,6 +233,12 @@ public class ${class.name} #else #set ( $pfx = "get" ) #end + /** + #set ( $desc = ${field.description.trim()} ) + #foreach ( $line in ${desc.split("\n")} ) + * ${line.trim()} + #end + */ #if ( $field.type == "java.util.List" || $field.type == "java.util.Properties" ) @Nonnull #end @@ -177,45 +248,122 @@ public class ${class.name} } #end + #if ( $locationTracking ) + /** + * Gets the location of the specified field in the input source. + */ + public InputLocation getLocation( Object key ) + { + if ( key instanceof String ) + { + switch ( ( String ) key ) + { + #if ( ! $class.superClass ) + case "": + return location; + #end + #foreach ( $field in $class.getFields($version) ) + case "${field.name}": + return ${field.name}Location; + #end + } + } + #if ( $class.superClass ) + return super.getLocation( key ); + #else + return locations != null ? locations.get( key ) : null; + #end + } + + #end + /** + * Creates a new builder with this object as the basis. + */ + @Nonnull + public Builder with() + { + return newBuilder( this ); + } #foreach ( $field in $allFields ) #set ( $cap = $Helper.capitalise( $field.name ) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + /** Creates a new ${class.name} instance using the specified ${field.name}. */ + @Nonnull public ${class.name} with${cap}( $type $field.name ) { - return newBuilder( this ).${field.name}( $field.name ).build(); + return with().${field.name}( $field.name ).build(); } #end + /** + * Creates a new ${class.name} instance. + * Equivalent to {@code newInstance( true )}. + * @see #newInstance(boolean) + */ + @Nonnull public static ${class.name} newInstance() { return newInstance( true ); } + /** + * Creates a new ${class.name} instance using default values or not. + * Equivalent to {@code newBuilder( withDefaults ).build()}. + */ + @Nonnull public static ${class.name} newInstance( boolean withDefaults ) { return newBuilder( withDefaults ).build(); } + /** + * Creates a new ${class.name} builder instance. + * Equivalent to {@code newBuilder( true )}. + * @see #newBuilder(boolean) + */ + @Nonnull public static Builder newBuilder() { return newBuilder( true ); } + /** + * Creates a new ${class.name} builder instance using default values or not. + */ + @Nonnull public static Builder newBuilder( boolean withDefaults ) { return new Builder( withDefaults ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + * Equivalent to {@code newBuilder( from, false )}. + */ + @Nonnull public static Builder newBuilder( ${class.name} from ) { return newBuilder( from, false ); } + /** + * Creates a new ${class.name} builder instance using the specified object as a basis. + */ + @Nonnull public static Builder newBuilder( ${class.name} from, boolean forceCopy ) { return new Builder( from, forceCopy ); } + /** + * Builder class used to create ${class.name} instances. + * @see #with() + * @see #newBuilder() + */ + @NotThreadSafe public static class Builder #if ( $class.superClass ) extends ${class.superClass}.Builder @@ -227,6 +375,9 @@ public class ${class.name} #end #foreach ( $field in $class.getFields($version) ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end #if ( $type == 'boolean' ) Boolean ${field.name}; #elseif ( $type == 'int' ) @@ -234,6 +385,9 @@ public class ${class.name} #else ${type} ${field.name}; #end + #end + #if ( ! $class.superClass && $locationTracking ) + Map locations; #end Builder( boolean withDefaults ) @@ -274,6 +428,7 @@ public class ${class.name} } #if ( $class == $root ) + @Nonnull public Builder modelEncoding( String modelEncoding ) { this.modelEncoding = modelEncoding; @@ -283,6 +438,10 @@ public class ${class.name} #end #foreach ( $field in $allFields ) #set ( $type = ${types.getOrDefault($field,${types.getOrDefault($field.type,$field.type)})} ) + #if ( $type.startsWith("List<") ) + #set ( $type = ${type.replace('List<','Collection<')} ) + #end + @Nonnull public Builder ${field.name}( ${type} ${field.name} ) { this.${field.name} = ${field.name}; @@ -291,6 +450,23 @@ public class ${class.name} #end + #if ( $locationTracking ) + @Nonnull + public Builder location( Object key, InputLocation location ) + { + if ( location != null ) + { + if ( this.locations == null ) + { + this.locations = new HashMap<>(); + } + this.locations.put( key, location ); + } + return this; + } + + #end + @Nonnull public ${class.name} build() { if ( base != null @@ -301,31 +477,38 @@ public class ${class.name} { return base; } + #if ( $locationTracking ) + Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); + InputLocation location = locations.remove( "" ); + #foreach ( $field in $allFields ) + InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + #end + #end return new ${class.name}( #if ( $class == $root ) modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), #end #foreach ( $field in $allFields ) - #if ( $field == ${allFields[${allFields.size()} - 1]} ) - #set ( $sep = "" ) - #else - #set ( $sep = "," ) - #end - #if ( $field.type == "java.util.List" ) - ${field.name} != null ? Collections.unmodifiableList( new ArrayList<>( ${field.name} ) ) : ( base != null ? base.${field.name} : Collections.emptyList() )${sep} - #elseif ( $field.type == "java.util.Properties" ) - new ROProperties( ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null ) )${sep} - #elseif ( $field.type == "boolean" || $field.type == "int" ) + #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) + #if ( $field.type == "boolean" || $field.type == "int" ) ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : ${field.defaultValue} )${sep} #else ${field.name} != null ? ${field.name} : ( base != null ? base.${field.name} : null )${sep} #end + #end + #if ( $locationTracking ) + locations, + location != null ? location : ( base != null ? base.location : null ), + #foreach ( $field in $allFields ) + #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) + ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} + #end #end ); } } - #foreach ( $cs in $class.allCodeSegments ) + #foreach ( $cs in $class.getCodeSegments($version) ) $cs.code #end } diff --git a/maven-plugin-api/src/main/mdo/reader.vm b/maven-plugin-api/src/main/mdo/reader.vm index dffe32d45bad..a3187be3f5b8 100644 --- a/maven-plugin-api/src/main/mdo/reader.vm +++ b/maven-plugin-api/src/main/mdo/reader.vm @@ -16,9 +16,11 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "${model.getDefault('package').getValue()}" ) -#set ( $package = "${basePackage}.io.xpp3" ) +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Reader" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -44,7 +46,7 @@ import java.util.Set; import org.apache.maven.api.annotations.Generated; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; @@ -61,13 +63,7 @@ public class ${className} public ${className}() { - this( new ContentTransformer() - { - public String transform( String source, String fieldName ) - { - return source; - } - } ); + this( ( s, f ) -> s ); } public ${className}( ContentTransformer contentTransformer ) diff --git a/maven-plugin-api/src/main/mdo/writer.vm b/maven-plugin-api/src/main/mdo/writer.vm index ad63caa768b3..e2740f45a4d3 100644 --- a/maven-plugin-api/src/main/mdo/writer.vm +++ b/maven-plugin-api/src/main/mdo/writer.vm @@ -16,9 +16,11 @@ specific language governing permissions and limitations under the License. *# -#set ( $basePackage = "${model.getDefault('package').getValue()}" ) -#set ( $package = "${basePackage}.io.xpp3" ) +#parse ( "src/main/mdo/common.vm" ) +# +#set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Writer" ) +# #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) #set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) #set ( $rootTag = $rootXml.tagName ) @@ -49,7 +51,7 @@ import org.apache.maven.api.annotations.Generated; import org.apache.maven.api.xml.Dom; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) -import ${basePackage}.${class.name}; +import ${packageModelV4}.${class.name}; #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; @@ -201,21 +203,26 @@ public class ${className} #set ( $fieldTagName = $field.name ) #end #set ( $fieldCapName = $Helper.capitalise( $field.name ) ) + #set ( $def = ${field.defaultValue} ) #if ( $field.type == "String" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.get${fieldCapName}(), serializer ); + #if ( ! $def ) + writeTag( "$fieldTagName", null, ${classLcapName}.get${fieldCapName}(), serializer ); + #else + writeTag( "$fieldTagName", "${def}", ${classLcapName}.get${fieldCapName}(), serializer ); + #end #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - #if ( ${field.defaultValue} == "true" ) - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); + #if ( ${def} == "true" ) + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? null : "false", serializer ); #else - writeTag( "$fieldTagName", "${field.defaultValue}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); + writeTag( "$fieldTagName", "${def}", ${classLcapName}.is${fieldCapName}() ? "true" : null, serializer ); #end #elseif ( $field.type == "int" ) - // TODO: name=${field.name} type=${field.type} + writeTag( "$fieldTagName", "${def}", Integer.toString( ${classLcapName}.get${fieldCapName}() ), serializer ); #elseif ( $field.type == "DOM" ) writeDom( ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) #set( $singularField = ${Helper.singular($fieldTagName)} ) - writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${field.defaultValue}", t, serializer ) ); + writeList( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer, t -> writeTag( "$singularField", "${def}", t, serializer ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) writeProperties( "$fieldTagName", ${classLcapName}.get${fieldCapName}(), serializer ); #elseif ( $field.to && $field.multiplicity == "1" ) diff --git a/maven-settings/src/main/mdo/common.vm b/maven-settings/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/maven-settings/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/maven-settings/src/main/mdo/merger.vm b/maven-settings/src/main/mdo/merger.vm index bbb9d9179ded..8358f306b080 100644 --- a/maven-settings/src/main/mdo/merger.vm +++ b/maven-settings/src/main/mdo/merger.vm @@ -16,15 +16,12 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Merger" ) # #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) -#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) -#set ( $rootTag = $rootXml.tagName ) -#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) -#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== @@ -118,6 +115,9 @@ public class ${className} if ( src != null && ( sourceDominant || tgt == null ) ) { builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); @@ -129,6 +129,9 @@ public class ${className} if ( tgt == null ) { builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else { @@ -136,6 +139,9 @@ public class ${className} merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "1" ) @@ -151,10 +157,16 @@ public class ${className} if ( merged == src ) { builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else if ( merged != tgt ) { builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "*" ) @@ -177,6 +189,16 @@ public class ${className} builder.configuration( tgt.merge( src ) ); } } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end diff --git a/maven-settings/src/main/mdo/model-v3.vm b/maven-settings/src/main/mdo/model-v3.vm index 31f6a8f9fb70..fe38c72ebcdf 100644 --- a/maven-settings/src/main/mdo/model-v3.vm +++ b/maven-settings/src/main/mdo/model-v3.vm @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageModelV3}" ) # diff --git a/maven-settings/src/main/mdo/reader.vm b/maven-settings/src/main/mdo/reader.vm index 15960ecd7283..a3187be3f5b8 100644 --- a/maven-settings/src/main/mdo/reader.vm +++ b/maven-settings/src/main/mdo/reader.vm @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Reader" ) @@ -62,13 +63,7 @@ public class ${className} public ${className}() { - this( new ContentTransformer() - { - public String transform( String source, String fieldName ) - { - return source; - } - } ); + this( ( s, f ) -> s ); } public ${className}( ContentTransformer contentTransformer ) diff --git a/maven-settings/src/main/mdo/writer.vm b/maven-settings/src/main/mdo/writer.vm index 9afca2daa603..e2740f45a4d3 100644 --- a/maven-settings/src/main/mdo/writer.vm +++ b/maven-settings/src/main/mdo/writer.vm @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Writer" ) diff --git a/maven-toolchain-model/src/main/mdo/common.vm b/maven-toolchain-model/src/main/mdo/common.vm new file mode 100644 index 000000000000..aa3d17a0398e --- /dev/null +++ b/maven-toolchain-model/src/main/mdo/common.vm @@ -0,0 +1,21 @@ +#* + 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. +*# +## +## Nothing special to do here +## \ No newline at end of file diff --git a/maven-toolchain-model/src/main/mdo/merger.vm b/maven-toolchain-model/src/main/mdo/merger.vm index bbb9d9179ded..8358f306b080 100644 --- a/maven-toolchain-model/src/main/mdo/merger.vm +++ b/maven-toolchain-model/src/main/mdo/merger.vm @@ -16,15 +16,12 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Merger" ) # #set ( $root = $model.getClass( $model.getRoot($version), $version ) ) -#set ( $rootXml = $Helper.xmlClassMetadata( $root ) ) -#set ( $rootTag = $rootXml.tagName ) -#set ( $rootUcapName = $Helper.capitalise( $root.name ) ) -#set ( $rootLcapName = $Helper.uncapitalise( $root.name ) ) # #MODELLO-VELOCITY#REDIRECT ${package.replace('.','/')}/${className}.java // =================== DO NOT EDIT THIS FILE ==================== @@ -118,6 +115,9 @@ public class ${className} if ( src != null && ( sourceDominant || tgt == null ) ) { builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } #elseif ( $field.type == "java.util.List" && $field.to == "String" && $field.multiplicity == "*" ) builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); @@ -129,6 +129,9 @@ public class ${className} if ( tgt == null ) { builder.${field.name}( src ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else { @@ -136,6 +139,9 @@ public class ${className} merged.putAll( sourceDominant ? target.get${capField}() : source.get${capField}() ); merged.putAll( sourceDominant ? source.get${capField}() : target.get${capField}() ); builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "1" ) @@ -151,10 +157,16 @@ public class ${className} if ( merged == src ) { builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", source.getLocation( "${field.name}" ) ); + #end } else if ( merged != tgt ) { builder.${field.name}( merged ); + #if ( $locationTracking ) + builder.location( "${field.name}", InputLocation.merge( target.getLocation( "${field.name}" ), source.getLocation( "${field.name}" ), sourceDominant ) ); + #end } } #elseif ( $field.to && $field.multiplicity == "*" ) @@ -177,6 +189,16 @@ public class ${className} builder.configuration( tgt.merge( src ) ); } } + #elseif ( $field.type == "boolean" ) + if ( sourceDominant ) + { + builder.${field.name}( source.is${capField}() ); + } + #elseif ( $field.type == "int" || $field.type == "java.nio.file.Path" ) + if ( sourceDominant ) + { + builder.${field.name}( source.get${capField}() ); + } #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end diff --git a/maven-toolchain-model/src/main/mdo/model-v3.vm b/maven-toolchain-model/src/main/mdo/model-v3.vm index 31f6a8f9fb70..fe38c72ebcdf 100644 --- a/maven-toolchain-model/src/main/mdo/model-v3.vm +++ b/maven-toolchain-model/src/main/mdo/model-v3.vm @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageModelV3}" ) # diff --git a/maven-toolchain-model/src/main/mdo/reader.vm b/maven-toolchain-model/src/main/mdo/reader.vm index 15960ecd7283..a3187be3f5b8 100644 --- a/maven-toolchain-model/src/main/mdo/reader.vm +++ b/maven-toolchain-model/src/main/mdo/reader.vm @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Reader" ) @@ -62,13 +63,7 @@ public class ${className} public ${className}() { - this( new ContentTransformer() - { - public String transform( String source, String fieldName ) - { - return source; - } - } ); + this( ( s, f ) -> s ); } public ${className}( ContentTransformer contentTransformer ) diff --git a/maven-toolchain-model/src/main/mdo/writer.vm b/maven-toolchain-model/src/main/mdo/writer.vm index 9afca2daa603..e2740f45a4d3 100644 --- a/maven-toolchain-model/src/main/mdo/writer.vm +++ b/maven-toolchain-model/src/main/mdo/writer.vm @@ -16,6 +16,7 @@ specific language governing permissions and limitations under the License. *# +#parse ( "src/main/mdo/common.vm" ) # #set ( $package = "${packageToolV4}" ) #set ( $className = "${model.name}Xpp3Writer" ) From de991f87e3d45691791bb70ace82eec166f402df Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 11:17:36 +0200 Subject: [PATCH 39/98] Do not merge distributionManagement.relocation --- .../org/apache/maven/model/merge/MavenModelMerger.java | 10 ++++++++++ 1 file changed, 10 insertions(+) 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 f025a3278be5..59c57cefa450 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 @@ -389,6 +389,16 @@ protected void mergeBuildBase_TestResources( BuildBase.Builder builder, } } + @Override + protected void mergeDistributionManagement_Relocation( DistributionManagement.Builder builder, + DistributionManagement target, + DistributionManagement source, + boolean sourceDominant, + Map context ) + { + } + + @Override protected void mergeDistributionManagement_Repository( DistributionManagement.Builder builder, DistributionManagement target, From 6fe60fd8bdd3833aaf914f10a53a0fefb1982c35 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 12:00:24 +0200 Subject: [PATCH 40/98] Fix settings merging --- .../org/apache/maven/settings/merge/MavenSettingsMerger.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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 69e8a35f0896..241310f74633 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 @@ -57,7 +57,7 @@ else if ( recessive == null ) recessive.setSourceLevel( recessiveSourceLevel ); - Settings.Builder merged = Settings.newBuilder(); + Settings.Builder merged = Settings.newBuilder( dominant ); List dominantActiveProfiles = dominant.getActiveProfiles(); List recessiveActiveProfiles = recessive.getActiveProfiles(); From d74f5639bf71f42f63ac4d60efc6fc324402cd00 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 15:13:45 +0200 Subject: [PATCH 41/98] Correctly handle property merge --- maven-model/src/main/mdo/merger.vm | 4 ++-- maven-plugin-api/src/main/mdo/merger.vm | 4 ++-- maven-settings/src/main/mdo/merger.vm | 4 ++-- maven-toolchain-model/src/main/mdo/merger.vm | 4 ++-- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/maven-model/src/main/mdo/merger.vm b/maven-model/src/main/mdo/merger.vm index 8358f306b080..e81c3baab302 100644 --- a/maven-model/src/main/mdo/merger.vm +++ b/maven-model/src/main/mdo/merger.vm @@ -123,10 +123,10 @@ public class ${className} builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) Properties src = source.get${capField}(); - if ( src != null ) + if ( !src.isEmpty() ) { Properties tgt = target.get${capField}(); - if ( tgt == null ) + if ( tgt.isEmpty() ) { builder.${field.name}( src ); #if ( $locationTracking ) diff --git a/maven-plugin-api/src/main/mdo/merger.vm b/maven-plugin-api/src/main/mdo/merger.vm index 8358f306b080..e81c3baab302 100644 --- a/maven-plugin-api/src/main/mdo/merger.vm +++ b/maven-plugin-api/src/main/mdo/merger.vm @@ -123,10 +123,10 @@ public class ${className} builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) Properties src = source.get${capField}(); - if ( src != null ) + if ( !src.isEmpty() ) { Properties tgt = target.get${capField}(); - if ( tgt == null ) + if ( tgt.isEmpty() ) { builder.${field.name}( src ); #if ( $locationTracking ) diff --git a/maven-settings/src/main/mdo/merger.vm b/maven-settings/src/main/mdo/merger.vm index 8358f306b080..e81c3baab302 100644 --- a/maven-settings/src/main/mdo/merger.vm +++ b/maven-settings/src/main/mdo/merger.vm @@ -123,10 +123,10 @@ public class ${className} builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) Properties src = source.get${capField}(); - if ( src != null ) + if ( !src.isEmpty() ) { Properties tgt = target.get${capField}(); - if ( tgt == null ) + if ( tgt.isEmpty() ) { builder.${field.name}( src ); #if ( $locationTracking ) diff --git a/maven-toolchain-model/src/main/mdo/merger.vm b/maven-toolchain-model/src/main/mdo/merger.vm index 8358f306b080..e81c3baab302 100644 --- a/maven-toolchain-model/src/main/mdo/merger.vm +++ b/maven-toolchain-model/src/main/mdo/merger.vm @@ -123,10 +123,10 @@ public class ${className} builder.${field.name}( merge( target.get${capField}(), source.get${capField}(), sourceDominant, e -> e ) ); #elseif ( $field.type == "java.util.Properties" && $field.to == "String" && $field.multiplicity == "*" ) Properties src = source.get${capField}(); - if ( src != null ) + if ( !src.isEmpty() ) { Properties tgt = target.get${capField}(); - if ( tgt == null ) + if ( tgt.isEmpty() ) { builder.${field.name}( src ); #if ( $locationTracking ) From 6e21551c5b72ee3e0e875c269c34676607ebdf4d Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 15:19:28 +0200 Subject: [PATCH 42/98] Use ${root.name} --- maven-model/src/main/mdo/reader-ex.vm | 331 ++--------------------- maven-model/src/main/mdo/reader.vm | 346 +++--------------------- maven-model/src/main/mdo/transformer.vm | 4 +- maven-model/src/main/mdo/writer-ex.vm | 5 +- 4 files changed, 73 insertions(+), 613 deletions(-) diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm index 47d1373d0da4..e2a2bb256993 100644 --- a/maven-model/src/main/mdo/reader-ex.vm +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -47,6 +47,8 @@ import java.util.Properties; import java.util.Set; import org.apache.maven.api.annotations.Generated; import org.apache.maven.internal.xml.DomBuilder; +import ${packageModelV4}.InputSource; +import ${packageModelV4}.InputLocation; #foreach ( $class in $model.allClasses ) import ${packageModelV4}.${class.name}; #end @@ -101,15 +103,15 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( Reader reader, boolean strict, InputSource source ) + public ${root.name} read( Reader reader, boolean strict, InputSource source ) throws IOException, XmlPullParserException { XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); parser.setInput( reader ); return read( parser, strict, source ); - } //-- Model read( Reader, boolean ) + } //-- ${root.name} read( Reader, boolean ) /** * Method read. @@ -119,13 +121,13 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( InputStream in, boolean strict, InputSource source ) + public ${root.name} read( InputStream in, boolean strict, InputSource source ) throws IOException, XmlPullParserException { return read( ReaderFactory.newXmlReader( in ), strict, source ); - } //-- Model read( InputStream, boolean ) + } //-- ${root.name} read( InputStream, boolean ) /** * Method read. @@ -135,9 +137,9 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( XmlPullParser parser, boolean strict, InputSource source ) + public ${root.name} read( XmlPullParser parser, boolean strict, InputSource source ) throws IOException, XmlPullParserException { $rootUcapName $rootLcapName = null; @@ -166,7 +168,7 @@ public class ${className} return $rootLcapName; } throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); - } //-- Model read( XmlPullParser, boolean ) + } //-- ${root.name} read( XmlPullParser, boolean ) #foreach ( $class in $model.allClasses ) #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) @@ -207,7 +209,7 @@ public class ${className} #if ( $field.type == "String" ) ${classLcapName}.${field.name}( interpolatedTrimmed( value, "$fieldTagName" ) ); #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, "${field.defaultValue}" ) ); + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( value, "$fieldTagName" ), "$fieldTagName", parser, strict, "${field.defaultValue}" ) ); #else // TODO: type=${field.type} to=${field.to} multiplicity=${field.multiplicity} #end @@ -246,10 +248,10 @@ public class ${className} ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); break; #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, ${field.defaultValue} ) ); break; #elseif ( $field.type == "int" ) - ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); break; #elseif ( $field.type == "DOM" ) ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); @@ -447,6 +449,16 @@ public class ${className} return eventType; } //-- int nextTag( XmlPullParser ) +#foreach ( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "boolean" || $field.type == "Boolean" ) + #set ( $hasBooleanField = true ) + #elseif ( $field.type == "int" || $field.type == "Integer" ) + #set ( $hasIntegerField = true ) + #end + #end +#end +#if ( $hasBooleanField ) /** * Method getBooleanValue. * @@ -458,214 +470,18 @@ public class ${className} * any. * @return boolean */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, boolean defaultValue ) throws XmlPullParserException { if ( s != null && s.length() != 0 ) { return Boolean.valueOf( s ).booleanValue(); } - if ( defaultValue != null ) - { - return Boolean.valueOf( defaultValue ).booleanValue(); - } - return false; + return defaultValue; } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) -#if ( "0" == "1" ) - /** - * Method getBooleanValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return boolean - */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - return getBooleanValue( s, attribute, parser, null ); - } //-- boolean getBooleanValue( String, String, XmlPullParser ) - - /** - * Method getByteValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return byte - */ - private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Byte.valueOf( s ).byteValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); - } - } - } - return 0; - } //-- byte getByteValue( String, String, XmlPullParser, boolean ) - - /** - * Method getCharacterValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return char - */ - private char getCharacterValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - if ( s != null ) - { - return s.charAt( 0 ); - } - return 0; - } //-- char getCharacterValue( String, String, XmlPullParser ) - - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - return getDateValue( s, attribute, null, parser ); - } //-- Date getDateValue( String, String, XmlPullParser ) - - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param dateFormat a dateFormat object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) - throws XmlPullParserException - { - if ( s != null ) - { - String effectiveDateFormat = dateFormat; - if ( dateFormat == null ) - { - effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; - } - if ( "long".equals( effectiveDateFormat ) ) - { - try - { - return new java.util.Date( Long.parseLong( s ) ); - } - catch ( NumberFormatException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } - } - else - { - try - { - DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); - return dateParser.parse( s ); - } - catch ( java.text.ParseException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } - } - } - return null; - } //-- Date getDateValue( String, String, String, XmlPullParser ) - - /** - * Method getDoubleValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return double - */ - private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Double.valueOf( s ).doubleValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); - } - } - } - return 0; - } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) - - /** - * Method getFloatValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return float - */ - private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Float.valueOf( s ).floatValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); - } - } - } - return 0; - } //-- float getFloatValue( String, String, XmlPullParser, boolean ) - +#end +#if ( $hasIntegerField ) /** * Method getIntegerValue. * @@ -677,7 +493,7 @@ public class ${className} * any. * @return int */ - private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) throws XmlPullParserException { if ( s != null ) @@ -694,97 +510,10 @@ public class ${className} } } } - return 0; + return defaultValue; } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) - /** - * Method getLongValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return long - */ - private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Long.valueOf( s ).longValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); - } - } - } - return 0; - } //-- long getLongValue( String, String, XmlPullParser, boolean ) - - /** - * Method getRequiredAttributeValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return String - */ - private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s == null ) - { - if ( strict ) - { - throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); - } - } - return s; - } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) - - /** - * Method getShortValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return short - */ - private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Short.valueOf( s ).shortValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); - } - } - } - return 0; - } //-- short getShortValue( String, String, XmlPullParser, boolean ) - #end - public static interface ContentTransformer { /** diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm index fd0bb50b26e0..cfc60bb33462 100644 --- a/maven-model/src/main/mdo/reader.vm +++ b/maven-model/src/main/mdo/reader.vm @@ -99,9 +99,9 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( Reader reader, boolean strict ) + public ${root.name} read( Reader reader, boolean strict ) throws IOException, XmlPullParserException { XmlPullParser parser = addDefaultEntities ? new MXParser(EntityReplacementMap.defaultEntityReplacementMap) : new MXParser( ); @@ -110,7 +110,7 @@ public class ${className} return read( parser, strict ); - } //-- Model read( Reader, boolean ) + } //-- ${root.name} read( Reader, boolean ) /** * @see ReaderFactory#newXmlReader @@ -119,13 +119,13 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( Reader reader ) + public ${root.name} read( Reader reader ) throws IOException, XmlPullParserException { return read( reader, true ); - } //-- Model read( Reader ) + } //-- ${root.name} read( Reader ) /** * Method read. @@ -135,13 +135,13 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( InputStream in, boolean strict ) + public ${root.name} read( InputStream in, boolean strict ) throws IOException, XmlPullParserException { return read( ReaderFactory.newXmlReader( in ), strict ); - } //-- Model read( InputStream, boolean ) + } //-- ${root.name} read( InputStream, boolean ) /** * Method read. @@ -150,13 +150,13 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( InputStream in ) + public ${root.name} read( InputStream in ) throws IOException, XmlPullParserException { return read( ReaderFactory.newXmlReader( in ) ); - } //-- Model read( InputStream ) + } //-- ${root.name} read( InputStream ) /** * Method read. @@ -166,9 +166,9 @@ public class ${className} * @throws IOException IOException if any. * @throws XmlPullParserException XmlPullParserException if * any. - * @return Model + * @return ${root.name} */ - public Model read( XmlPullParser parser, boolean strict ) + public ${root.name} read( XmlPullParser parser, boolean strict ) throws IOException, XmlPullParserException { $rootUcapName $rootLcapName = null; @@ -197,7 +197,7 @@ public class ${className} return $rootLcapName; } throw new XmlPullParserException( "Expected root element '${rootTag}' but found no element at all: invalid XML document", parser, null ); - } //-- Model read( XmlPullParser, boolean ) + } //-- ${root.name} read( XmlPullParser, boolean ) #foreach ( $class in $model.allClasses ) #if ( $class.name != "InputSource" && $class.name != "InputLocation" ) @@ -272,10 +272,10 @@ public class ${className} ${classLcapName}.${field.name}( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ) ); break; #elseif ( $field.type == "boolean" || $field.type == "Boolean" ) - ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + ${classLcapName}.${field.name}( getBooleanValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, ${field.defaultValue} ) ); break; #elseif ( $field.type == "int" ) - ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, "${field.defaultValue}" ) ); + ${classLcapName}.${field.name}( getIntegerValue( interpolatedTrimmed( parser.nextText(), "${fieldTagName}" ), "${fieldTagName}", parser, strict, ${field.defaultValue} ) ); break; #elseif ( $field.type == "DOM" ) ${classLcapName}.${field.name}( DomBuilder.build( parser, true ) ); @@ -417,31 +417,6 @@ public class ${className} } } //-- void checkUnknownElement( XmlPullParser, boolean ) - /** - * Method getBooleanValue. - * - * @param s a s object. - * @param defaultValue a defaultValue object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return boolean - */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, String defaultValue ) - throws XmlPullParserException - { - if ( s != null && s.length() != 0 ) - { - return Boolean.valueOf( s ).booleanValue(); - } - if ( defaultValue != null ) - { - return Boolean.valueOf( defaultValue ).booleanValue(); - } - return false; - } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) - /** * Method getTrimmedValue. * @@ -493,200 +468,39 @@ public class ${className} return eventType; } //-- int nextTag( XmlPullParser ) -#if ( "0" == "1" ) +#foreach ( $class in $model.allClasses ) + #foreach ( $field in $class.getFields($version) ) + #if ( $field.type == "boolean" || $field.type == "Boolean" ) + #set ( $hasBooleanField = true ) + #elseif ( $field.type == "int" || $field.type == "Integer" ) + #set ( $hasIntegerField = true ) + #end + #end +#end +#if ( $hasBooleanField ) /** * Method getBooleanValue. * * @param s a s object. + * @param defaultValue a defaultValue object. * @param parser a parser object. * @param attribute a attribute object. * @throws XmlPullParserException XmlPullParserException if * any. * @return boolean */ - private boolean getBooleanValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - return getBooleanValue( s, attribute, parser, null ); - } //-- boolean getBooleanValue( String, String, XmlPullParser ) - - /** - * Method getByteValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return byte - */ - private byte getByteValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Byte.valueOf( s ).byteValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a byte", parser, nfe ); - } - } - } - return 0; - } //-- byte getByteValue( String, String, XmlPullParser, boolean ) - - /** - * Method getCharacterValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return char - */ - private char getCharacterValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - if ( s != null ) - { - return s.charAt( 0 ); - } - return 0; - } //-- char getCharacterValue( String, String, XmlPullParser ) - - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, XmlPullParser parser ) - throws XmlPullParserException - { - return getDateValue( s, attribute, null, parser ); - } //-- Date getDateValue( String, String, XmlPullParser ) - - /** - * Method getDateValue. - * - * @param s a s object. - * @param parser a parser object. - * @param dateFormat a dateFormat object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return Date - */ - private Date getDateValue( String s, String attribute, String dateFormat, XmlPullParser parser ) - throws XmlPullParserException - { - if ( s != null ) - { - String effectiveDateFormat = dateFormat; - if ( dateFormat == null ) - { - effectiveDateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS"; - } - if ( "long".equals( effectiveDateFormat ) ) - { - try - { - return new java.util.Date( Long.parseLong( s ) ); - } - catch ( NumberFormatException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } - } - else - { - try - { - DateFormat dateParser = new java.text.SimpleDateFormat( effectiveDateFormat, java.util.Locale.US ); - return dateParser.parse( s ); - } - catch ( java.text.ParseException e ) - { - throw new XmlPullParserException( e.getMessage(), parser, e ); - } - } - } - return null; - } //-- Date getDateValue( String, String, String, XmlPullParser ) - - /** - * Method getDoubleValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return double - */ - private double getDoubleValue( String s, String attribute, XmlPullParser parser, boolean strict ) + private boolean getBooleanValue( String s, String attribute, XmlPullParser parser, boolean defaultValue ) throws XmlPullParserException { - if ( s != null ) - { - try - { - return Double.valueOf( s ).doubleValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); - } - } - } - return 0; - } //-- double getDoubleValue( String, String, XmlPullParser, boolean ) - - /** - * Method getFloatValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return float - */ - private float getFloatValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) + if ( s != null && s.length() != 0 ) { - try - { - return Float.valueOf( s ).floatValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a floating point number", parser, nfe ); - } - } + return Boolean.valueOf( s ).booleanValue(); } - return 0; - } //-- float getFloatValue( String, String, XmlPullParser, boolean ) + return defaultValue; + } //-- boolean getBooleanValue( String, String, XmlPullParser, String ) +#end +#if ( $hasIntegerField ) /** * Method getIntegerValue. * @@ -698,7 +512,7 @@ public class ${className} * any. * @return int */ - private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict ) + private int getIntegerValue( String s, String attribute, XmlPullParser parser, boolean strict, int defaultValue ) throws XmlPullParserException { if ( s != null ) @@ -715,95 +529,9 @@ public class ${className} } } } - return 0; + return defaultValue; } //-- int getIntegerValue( String, String, XmlPullParser, boolean ) - /** - * Method getLongValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return long - */ - private long getLongValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Long.valueOf( s ).longValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a long integer", parser, nfe ); - } - } - } - return 0; - } //-- long getLongValue( String, String, XmlPullParser, boolean ) - - /** - * Method getRequiredAttributeValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return String - */ - private String getRequiredAttributeValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s == null ) - { - if ( strict ) - { - throw new XmlPullParserException( "Missing required value for attribute '" + attribute + "'", parser, null ); - } - } - return s; - } //-- String getRequiredAttributeValue( String, String, XmlPullParser, boolean ) - - /** - * Method getShortValue. - * - * @param s a s object. - * @param strict a strict object. - * @param parser a parser object. - * @param attribute a attribute object. - * @throws XmlPullParserException XmlPullParserException if - * any. - * @return short - */ - private short getShortValue( String s, String attribute, XmlPullParser parser, boolean strict ) - throws XmlPullParserException - { - if ( s != null ) - { - try - { - return Short.valueOf( s ).shortValue(); - } - catch ( NumberFormatException nfe ) - { - if ( strict ) - { - throw new XmlPullParserException( "Unable to parse element '" + attribute + "', must be a short integer", parser, nfe ); - } - } - } - return 0; - } //-- short getShortValue( String, String, XmlPullParser, boolean ) - #end public static interface ContentTransformer { diff --git a/maven-model/src/main/mdo/transformer.vm b/maven-model/src/main/mdo/transformer.vm index f309df1a3985..8c7380b2be57 100644 --- a/maven-model/src/main/mdo/transformer.vm +++ b/maven-model/src/main/mdo/transformer.vm @@ -63,10 +63,10 @@ public class ${className} /** * Transforms the given model */ - public Model visit( Model target ) + public ${root.name} visit( ${root.name} target ) { Objects.requireNonNull( target, "target cannot be null" ); - return transformModel( target ); + return transform${root.name}( target ); } /** diff --git a/maven-model/src/main/mdo/writer-ex.vm b/maven-model/src/main/mdo/writer-ex.vm index cae13506df70..de458ed3c366 100644 --- a/maven-model/src/main/mdo/writer-ex.vm +++ b/maven-model/src/main/mdo/writer-ex.vm @@ -48,11 +48,14 @@ import java.util.Objects; import java.util.Properties; import java.util.Set; import org.apache.maven.api.annotations.Generated; -import org.apache.maven.api.model.InputLocationTracker; +import ${packageModelV4}.InputLocation; +import ${packageModelV4}.InputLocationTracker; import org.apache.maven.api.xml.Dom; import org.apache.maven.internal.xml.DomBuilder; #foreach ( $class in $model.allClasses ) + #if ( $class.name != "InputLocation" ) import ${packageModelV4}.${class.name}; + #end #end import org.codehaus.plexus.util.ReaderFactory; import org.codehaus.plexus.util.xml.pull.EntityReplacementMap; From 389707ffc43c4674f8462903ffba43148f1507f5 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 15:20:40 +0200 Subject: [PATCH 43/98] Handle case where a class has no defined fields --- api/maven-api-model/src/main/mdo/model.vm | 9 ++++++--- api/maven-api-settings/src/main/mdo/model.vm | 9 ++++++--- api/maven-api-toolchain/src/main/mdo/model.vm | 9 ++++++--- 3 files changed, 18 insertions(+), 9 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index c981c2bd5138..5c916583b98b 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -150,7 +150,8 @@ public class ${class.name} #end #if ( $locationTracking ) Map locations, - InputLocation location, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + InputLocation location${sep} #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) InputLocation ${field.name}Location${sep} @@ -166,7 +167,8 @@ public class ${class.name} #end #if ( $locationTracking ) locations, - location, + #set ( $sep = "#if(${inheritedFields.size()}>0),#end" ) + location${sep} #foreach ( $field in $inheritedFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) ${field.name}Location${sep} @@ -498,7 +500,8 @@ public class ${class.name} #end #if ( $locationTracking ) locations, - location != null ? location : ( base != null ? base.location : null ), + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + location != null ? location : ( base != null ? base.location : null )${sep} #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm index c981c2bd5138..5c916583b98b 100644 --- a/api/maven-api-settings/src/main/mdo/model.vm +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -150,7 +150,8 @@ public class ${class.name} #end #if ( $locationTracking ) Map locations, - InputLocation location, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + InputLocation location${sep} #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) InputLocation ${field.name}Location${sep} @@ -166,7 +167,8 @@ public class ${class.name} #end #if ( $locationTracking ) locations, - location, + #set ( $sep = "#if(${inheritedFields.size()}>0),#end" ) + location${sep} #foreach ( $field in $inheritedFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) ${field.name}Location${sep} @@ -498,7 +500,8 @@ public class ${class.name} #end #if ( $locationTracking ) locations, - location != null ? location : ( base != null ? base.location : null ), + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + location != null ? location : ( base != null ? base.location : null )${sep} #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm index c981c2bd5138..5c916583b98b 100644 --- a/api/maven-api-toolchain/src/main/mdo/model.vm +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -150,7 +150,8 @@ public class ${class.name} #end #if ( $locationTracking ) Map locations, - InputLocation location, + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + InputLocation location${sep} #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) InputLocation ${field.name}Location${sep} @@ -166,7 +167,8 @@ public class ${class.name} #end #if ( $locationTracking ) locations, - location, + #set ( $sep = "#if(${inheritedFields.size()}>0),#end" ) + location${sep} #foreach ( $field in $inheritedFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${inheritedFields[${inheritedFields.size()} - 1]}),#end" ) ${field.name}Location${sep} @@ -498,7 +500,8 @@ public class ${class.name} #end #if ( $locationTracking ) locations, - location != null ? location : ( base != null ? base.location : null ), + #set ( $sep = "#if(${allFields.size()}>0),#end" ) + location != null ? location : ( base != null ? base.location : null )${sep} #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}&&$field!=${allFields[${allFields.size()} - 1]}),#end" ) ${field.name}Location != null ? ${field.name}Location : ( base != null ? base.${field.name}Location : null )${sep} From dd83edd312bf8c8b06b863ef0b2944a9207afabd Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 16:09:54 +0200 Subject: [PATCH 44/98] Fix toolchain ITs --- .../apache/maven/toolchain/DefaultToolchainManager.java | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java index a5fa002c2e3c..74cb9c6c0b87 100644 --- a/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java +++ b/maven-core/src/main/java/org/apache/maven/toolchain/DefaultToolchainManager.java @@ -32,7 +32,7 @@ import org.apache.maven.execution.MavenSession; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; -import org.apache.maven.api.toolchain.ToolchainModel; +import org.apache.maven.toolchain.model.ToolchainModel; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -89,8 +89,7 @@ public Toolchain getToolchainFromBuildContext( String type, MavenSession session @Override public List getToolchains( MavenSession session, String type, Map requirements ) { - List models = org.apache.maven.toolchain.model.ToolchainModel.toolchainModelToApiV4( - session.getRequest().getToolchains().get( type ) ); + List models = session.getRequest().getToolchains().get( type ); return selectToolchains( models, type, requirements ); } @@ -115,9 +114,7 @@ private List selectToolchains( List models, String ty { try { - org.apache.maven.toolchain.model.ToolchainModel tm = - new org.apache.maven.toolchain.model.ToolchainModel( model ); - ToolchainPrivate toolchain = fact.createToolchain( tm ); + ToolchainPrivate toolchain = fact.createToolchain( model ); if ( requirements == null || toolchain.matchesRequirements( requirements ) ) { toolchains.add( toolchain ); From 4664e5662f4273e5b293d67462d38d2a59779322 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 8 Apr 2022 23:10:53 +0200 Subject: [PATCH 45/98] Fix profile activation issue --- api/maven-api-model/src/main/mdo/maven.mdo | 30 ++++++++++++++++++- .../apache/maven/settings/SettingsUtils.java | 8 ++--- 2 files changed, 32 insertions(+), 6 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index 4d69c741f706..90c5282fb1fa 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -2488,7 +2488,35 @@ - 4.0.0+ + 4.0.0/4.1.0 + + + + + + 5.0.0+ Date: Fri, 8 Apr 2022 23:23:31 +0200 Subject: [PATCH 46/98] Implement more methods on the WrapperProperties --- .../java/org/apache/maven/model/WrapperProperties.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java b/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java index cffe824b73b0..00a6dec175d1 100644 --- a/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java +++ b/maven-model/src/main/java/org/apache/maven/model/WrapperProperties.java @@ -320,19 +320,19 @@ public synchronized void load( InputStream inStream ) throws IOException @Override public void save( OutputStream out, String comments ) { - throw new UnsupportedOperationException(); + getter.get().save( out, comments ); } @Override public void store( Writer writer, String comments ) throws IOException { - throw new UnsupportedOperationException(); + getter.get().store( writer, comments ); } @Override public void store( OutputStream out, String comments ) throws IOException { - throw new UnsupportedOperationException(); + getter.get().store( out, comments ); } @Override @@ -344,13 +344,13 @@ public synchronized void loadFromXML( InputStream in ) throws IOException, Inval @Override public void storeToXML( OutputStream os, String comment ) throws IOException { - throw new UnsupportedOperationException(); + getter.get().storeToXML( os, comment ); } @Override public void storeToXML( OutputStream os, String comment, String encoding ) throws IOException { - throw new UnsupportedOperationException(); + getter.get().storeToXML( os, comment, encoding ); } } From eb16ad49eba06a5ca8cae19772ee0ebad91364ae Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Sat, 9 Apr 2022 16:05:59 +0200 Subject: [PATCH 47/98] Fix model encoding, wrapper list item removal --- api/maven-api-model/src/main/mdo/maven.mdo | 7 ++++++- api/maven-api-model/src/main/mdo/model.vm | 2 +- api/maven-api-settings/src/main/mdo/model.vm | 2 +- api/maven-api-toolchain/src/main/mdo/model.vm | 2 +- .../src/main/java/org/apache/maven/model/BaseObject.java | 2 +- maven-model/src/main/mdo/model-v3.vm | 6 +++--- maven-model/src/main/mdo/reader-ex.vm | 3 +++ maven-model/src/main/mdo/reader.vm | 3 +++ maven-plugin-api/src/main/mdo/model.vm | 2 +- maven-plugin-api/src/main/mdo/reader.vm | 3 +++ maven-settings/src/main/mdo/reader.vm | 3 +++ maven-toolchain-model/src/main/mdo/reader.vm | 3 +++ 12 files changed, 29 insertions(+), 9 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index 90c5282fb1fa..c4fa4802c727 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -377,7 +377,12 @@ public void setPomFile( java.io.File pomFile ) { - delegate = getDelegate().withPomFile( pomFile.toPath() ); + update( getDelegate().withPomFile( pomFile != null ? pomFile.toPath() : null ) ); + } + + public void setModelEncoding( String modelEncoding ) + { + update( getDelegate().with().modelEncoding( modelEncoding ).build() ); } /** diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 5c916583b98b..95967c58b355 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -488,7 +488,7 @@ public class ${class.name} #end return new ${class.name}( #if ( $class == $root ) - modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), #end #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm index 5c916583b98b..95967c58b355 100644 --- a/api/maven-api-settings/src/main/mdo/model.vm +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -488,7 +488,7 @@ public class ${class.name} #end return new ${class.name}( #if ( $class == $root ) - modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), #end #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm index 5c916583b98b..95967c58b355 100644 --- a/api/maven-api-toolchain/src/main/mdo/model.vm +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -488,7 +488,7 @@ public class ${class.name} #end return new ${class.name}( #if ( $class == $root ) - modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), #end #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) diff --git a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java index 9c583b6839d2..d80058adc4a2 100644 --- a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java +++ b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java @@ -52,7 +52,7 @@ public void setParent( BaseObject parent ) this.parent = parent; } - protected void update( Object newDelegate ) + public void update( Object newDelegate ) { if ( delegate != newDelegate ) { diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 04d60d427044..9c718c23ed2e 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -174,12 +174,12 @@ public class ${class.name} { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) return new WrapperList<${field.to}, org.apache.maven.api.model.${field.to}>( - getDelegate()::get${cap}, l -> update( getDelegate().with${cap}( l ) ), + () -> 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( getDelegate()::get${cap}, this::set${cap}, s -> s, s -> s ); + return new WrapperList( () -> 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" ) diff --git a/maven-model/src/main/mdo/reader-ex.vm b/maven-model/src/main/mdo/reader-ex.vm index e2a2bb256993..683d0a21e4a1 100644 --- a/maven-model/src/main/mdo/reader-ex.vm +++ b/maven-model/src/main/mdo/reader-ex.vm @@ -319,6 +319,9 @@ public class ${className} } ${classLcapName}.location( childName, new InputLocation( line, column, source, locations ) ); } + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); + #end return ${classLcapName}.build(); } diff --git a/maven-model/src/main/mdo/reader.vm b/maven-model/src/main/mdo/reader.vm index cfc60bb33462..caa2f1059499 100644 --- a/maven-model/src/main/mdo/reader.vm +++ b/maven-model/src/main/mdo/reader.vm @@ -338,6 +338,9 @@ public class ${className} } } } + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); + #end return ${classLcapName}.build(); } diff --git a/maven-plugin-api/src/main/mdo/model.vm b/maven-plugin-api/src/main/mdo/model.vm index c981c2bd5138..e995fa6e9478 100644 --- a/maven-plugin-api/src/main/mdo/model.vm +++ b/maven-plugin-api/src/main/mdo/model.vm @@ -486,7 +486,7 @@ public class ${class.name} #end return new ${class.name}( #if ( $class == $root ) - modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : null ), + modelEncoding != null ? modelEncoding : ( base != null ? base.modelEncoding : "UTF-8" ), #end #foreach ( $field in $allFields ) #set ( $sep = "#if(${locationTracking}||$field!=${allFields[${allFields.size()} - 1]}),#end" ) diff --git a/maven-plugin-api/src/main/mdo/reader.vm b/maven-plugin-api/src/main/mdo/reader.vm index a3187be3f5b8..a575b6534b94 100644 --- a/maven-plugin-api/src/main/mdo/reader.vm +++ b/maven-plugin-api/src/main/mdo/reader.vm @@ -818,6 +818,9 @@ public class ${className} #if ( $Helper.isFlatItems( $field ) ) ${classLcapName}.${field.name}( ${field.name} ); #end + #end + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); #end return ${classLcapName}.build(); } diff --git a/maven-settings/src/main/mdo/reader.vm b/maven-settings/src/main/mdo/reader.vm index a3187be3f5b8..a575b6534b94 100644 --- a/maven-settings/src/main/mdo/reader.vm +++ b/maven-settings/src/main/mdo/reader.vm @@ -818,6 +818,9 @@ public class ${className} #if ( $Helper.isFlatItems( $field ) ) ${classLcapName}.${field.name}( ${field.name} ); #end + #end + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); #end return ${classLcapName}.build(); } diff --git a/maven-toolchain-model/src/main/mdo/reader.vm b/maven-toolchain-model/src/main/mdo/reader.vm index a3187be3f5b8..a575b6534b94 100644 --- a/maven-toolchain-model/src/main/mdo/reader.vm +++ b/maven-toolchain-model/src/main/mdo/reader.vm @@ -818,6 +818,9 @@ public class ${className} #if ( $Helper.isFlatItems( $field ) ) ${classLcapName}.${field.name}( ${field.name} ); #end + #end + #if ( $class == $root ) + ${classLcapName}.modelEncoding( parser.getInputEncoding() ); #end return ${classLcapName}.build(); } From 6f3cc2ec0b21f343309a888823bee6201f200306 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 11 Apr 2022 08:02:05 +0200 Subject: [PATCH 48/98] Revert api changes in the maven-model-builder --- .../apache/maven/api/model/InputLocation.java | 2 +- .../maven/profiles/DefaultProfileManager.java | 9 +- .../validation/DefaultModelValidator.java | 2 +- .../internal/builder/BuilderCommon.java | 2 +- .../DefaultLifecycleBindingsInjector.java | 6 +- .../project/DefaultModelBuildingListener.java | 2 +- .../maven/project/DefaultProjectBuilder.java | 32 +- .../ConsumerModelSourceTransformerTest.java | 2 +- .../DefaultBuildPomXMLFilterFactory.java | 2 +- .../model/building/DefaultModelBuilder.java | 331 ++++++++---------- .../building/DefaultModelBuilderFactory.java | 9 +- .../building/DefaultModelBuildingEvent.java | 4 +- .../building/DefaultModelBuildingRequest.java | 4 +- .../building/DefaultModelBuildingResult.java | 4 +- .../model/building/DefaultModelProblem.java | 2 +- .../DefaultModelProblemCollector.java | 2 +- .../building/DefaultTransformerContext.java | 2 +- .../building/FilterModelBuildingRequest.java | 4 +- .../maven/model/building/ModelBuilder.java | 2 +- .../model/building/ModelBuildingEvent.java | 2 +- .../building/ModelBuildingException.java | 2 +- .../model/building/ModelBuildingRequest.java | 4 +- .../model/building/ModelBuildingResult.java | 4 +- .../maven/model/building/ModelData.java | 2 +- .../ModelProblemCollectorRequest.java | 2 +- .../model/building/ModelProblemUtils.java | 14 +- .../model/building/TransformerContext.java | 2 +- .../AbstractStringBasedModelInterpolator.java | 8 + .../interpolation/ModelInterpolator.java | 3 + .../maven/model/io/DefaultModelReader.java | 5 + .../DefaultDependencyManagementInjector.java | 5 +- .../DefaultPluginManagementInjector.java | 5 +- .../DependencyManagementInjector.java | 4 +- .../management/PluginManagementInjector.java | 4 +- .../path/DefaultModelPathTranslator.java | 12 +- .../model/path/DefaultModelUrlNormalizer.java | 47 +-- .../maven/model/path/ModelPathTranslator.java | 4 +- .../maven/model/path/ModelUrlNormalizer.java | 4 +- .../DefaultPluginConfigurationExpander.java | 52 ++- .../DefaultReportConfigurationExpander.java | 37 +- .../plugin/DefaultReportingConverter.java | 211 +++++------ .../plugin/LifecycleBindingsInjector.java | 4 +- .../plugin/PluginConfigurationExpander.java | 4 +- .../plugin/ReportConfigurationExpander.java | 4 +- .../model/plugin/ReportingConverter.java | 4 +- .../model/profile/DefaultProfileInjector.java | 19 +- .../model/profile/DefaultProfileSelector.java | 4 +- .../maven/model/profile/ProfileInjector.java | 6 +- .../maven/model/profile/ProfileSelector.java | 2 +- .../activation/FileProfileActivator.java | 6 +- .../JdkVersionProfileActivator.java | 4 +- .../OperatingSystemProfileActivator.java | 6 +- .../profile/activation/ProfileActivator.java | 2 +- .../activation/PropertyProfileActivator.java | 6 +- .../resolution/WorkspaceModelResolver.java | 2 +- .../validation/DefaultModelValidator.java | 34 +- .../model/validation/ModelValidator.java | 2 +- .../DefaultModelBuilderFactoryTest.java | 3 +- .../building/DefaultModelBuilderTest.java | 17 +- .../building/SimpleProblemCollector.java | 2 +- .../AbstractProfileActivatorTest.java | 2 +- .../validation/DefaultModelValidatorTest.java | 4 +- .../DefaultArtifactDescriptorReader.java | 2 +- 63 files changed, 448 insertions(+), 547 deletions(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java index 98d9ef8a29fe..fef494a5e517 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -60,7 +60,7 @@ public InputLocation( int lineNumber, int columnNumber, InputSource source, Obje this.lineNumber = lineNumber; this.columnNumber = columnNumber; this.source = source; - this.locations = selfLocationKey != null + this.locations = selfLocationKey != null ? Collections.singletonMap( selfLocationKey, this ) : Collections.emptyMap(); } diff --git a/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java b/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java index bc4b7dae57d7..11dc0a332229 100644 --- a/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java +++ b/maven-compat/src/main/java/org/apache/maven/profiles/DefaultProfileManager.java @@ -32,12 +32,10 @@ import org.codehaus.plexus.logging.Logger; import java.util.ArrayList; -import java.util.Collection; import java.util.LinkedHashMap; import java.util.List; import java.util.Map; import java.util.Properties; -import java.util.stream.Collectors; /** * DefaultProfileManager @@ -187,10 +185,7 @@ public List getActiveProfiles() final List errors = new ArrayList<>(); - Collection values = profilesById.values(); - List list = - values.stream().map( Profile::getDelegate ).collect( Collectors.toList() ); - List profiles = profileSelector.getActiveProfiles( list, context, req -> + List profiles = profileSelector.getActiveProfiles( profilesById.values(), context, req -> { if ( !ModelProblem.Severity.WARNING.equals( req.getSeverity() ) ) { @@ -203,7 +198,7 @@ public List getActiveProfiles() throw errors.get( 0 ); } - return Profile.profileToApiV3( profiles ); + return profiles; } /* (non-Javadoc) diff --git a/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java b/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java index 4882387690d3..6406b5844dbd 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java +++ b/maven-compat/src/main/java/org/apache/maven/project/validation/DefaultModelValidator.java @@ -49,7 +49,7 @@ public ModelValidationResult validate( Model model ) SimpleModelProblemCollector problems = new SimpleModelProblemCollector( result ); - modelValidator.validateEffectiveModel( model.getDelegate(), request, problems ); + modelValidator.validateEffectiveModel( model, request, problems ); return result; } diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java index 034db66a4c36..a493e5859a26 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/builder/BuilderCommon.java @@ -179,7 +179,7 @@ public MavenExecutionPlan resolveBuildPlan( MavenSession session, MavenProject p .map( MojoExecution::getPlugin ) .filter( p -> p.getLocation( "version" ) != null && p.getLocation( "version" ).getSource() != null - && p.getLocation( "version" ).getSource().getModelId().equals( defaulModelId ) ) + && defaulModelId.equals( p.getLocation( "version" ).getSource().getModelId() ) ) .distinct() .map( Plugin::getArtifactId ) // managed by us, groupId is always o.a.m.plugins .collect( Collectors.toList() ); diff --git a/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java b/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java index eaaeb100cdfb..688b60908960 100644 --- a/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java +++ b/maven-core/src/main/java/org/apache/maven/model/plugin/DefaultLifecycleBindingsInjector.java @@ -66,7 +66,8 @@ public DefaultLifecycleBindingsInjector( LifeCyclePluginAnalyzer lifecycle ) this.lifecycle = lifecycle; } - public Model injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void injectLifecycleBindings( org.apache.maven.model.Model model, ModelBuildingRequest request, + ModelProblemCollector problems ) { String packaging = model.getPackaging(); @@ -87,9 +88,8 @@ else if ( !defaultPlugins.isEmpty() ) Model lifecycleModel = Model.newBuilder() .build( Build.newBuilder().plugins( plugins ).build() ) .build(); - model = merger.merge( model, lifecycleModel ); + model.update( merger.merge( model.getDelegate(), lifecycleModel ) ); } - return model; } /** diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java b/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java index 2147d48085f1..ca6079426dcf 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultModelBuildingListener.java @@ -77,7 +77,7 @@ public MavenProject getProject() @Override public void buildExtensionsAssembled( ModelBuildingEvent event ) { - Model model = new Model( event.getModel() ); + Model model = event.getModel(); try { diff --git a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java index 95a5ee118978..7fe5a23b1314 100644 --- a/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/project/DefaultProjectBuilder.java @@ -21,7 +21,6 @@ import java.io.File; import java.io.IOException; -import java.nio.file.Path; import java.util.AbstractMap; import java.util.ArrayList; import java.util.Arrays; @@ -262,9 +261,9 @@ private DependencyResolutionResult resolveDependencies( MavenProject project, Re return resolutionResult; } - private List getProfileIds( List profiles ) + private List getProfileIds( List profiles ) { - return profiles.stream().map( org.apache.maven.api.model.Profile::getId ).collect( Collectors.toList() ); + return profiles.stream().map( org.apache.maven.model.Profile::getId ).collect( Collectors.toList() ); } private ModelBuildingRequest getModelBuildingRequest( InternalConfig config ) @@ -281,9 +280,7 @@ private ModelBuildingRequest getModelBuildingRequest( InternalConfig config ) request.setValidationLevel( configuration.getValidationLevel() ); request.setProcessPlugins( configuration.isProcessPlugins() ); - request.setProfiles( configuration.getProfiles() != null - ? configuration.getProfiles().stream().map( Profile::getDelegate ).collect( Collectors.toList() ) - : null ); + request.setProfiles( configuration.getProfiles() ); request.setActiveProfileIds( configuration.getActiveProfileIds() ); request.setInactiveProfileIds( configuration.getInactiveProfileIds() ); request.setSystemProperties( configuration.getSystemProperties() ); @@ -488,7 +485,7 @@ private boolean build( List results, List noErrors = false; } - Model model = new Model( result.getFileModel() ); + Model model = result.getFileModel(); poolBuilder.put( model.getPomFile().toPath(), model ); @@ -520,7 +517,7 @@ private boolean build( List results, List ModelProblem problem = new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile + " does not exist", ModelProblem.Severity.ERROR, ModelProblem.Version.BASE, - model.getDelegate(), -1, -1, null ); + model, -1, -1, null ); result.getProblems().add( problem ); noErrors = false; @@ -557,7 +554,7 @@ private boolean build( List results, List ModelProblem problem = new DefaultModelProblem( "Child module " + moduleFile + " of " + pomFile + " forms aggregation cycle " + buffer, ModelProblem.Severity.ERROR, - ModelProblem.Version.BASE, model.getDelegate(), -1, -1, null ); + ModelProblem.Version.BASE, model, -1, -1, null ); result.getProblems().add( problem ); noErrors = false; @@ -661,7 +658,7 @@ private boolean build( List results, List p } else { - project.setModel( new Model( interimResult.result.getEffectiveModel() ) ); + project.setModel( interimResult.result.getEffectiveModel() ); result = new DefaultProjectBuildingResult( project, e.getProblems(), null ); } @@ -679,8 +676,8 @@ private void initProject( MavenProject project, Map projects boolean buildParentIfNotExisting, ModelBuildingResult result, Map profilesXmls, ProjectBuildingRequest projectBuildingRequest ) { - project.setModel( new Model( result.getEffectiveModel() ) ); - project.setOriginalModel( new Model( result.getFileModel() ) ); + project.setModel( result.getEffectiveModel() ); + project.setOriginalModel( result.getFileModel() ); initParent( project, projects, buildParentIfNotExisting, result, projectBuildingRequest ); @@ -698,8 +695,8 @@ private void initProject( MavenProject project, Map projects } List activeProfiles = new ArrayList<>(); - activeProfiles.addAll( Profile.profileToApiV3( result.getActivePomProfiles( result.getModelIds().get( 0 ) ) ) ); - activeProfiles.addAll( Profile.profileToApiV3( result.getActiveExternalProfiles() ) ); + activeProfiles.addAll( result.getActivePomProfiles( result.getModelIds().get( 0 ) ) ); + activeProfiles.addAll( result.getActiveExternalProfiles() ); project.setActiveProfiles( activeProfiles ); project.setInjectedProfileIds( "external", getProfileIds( result.getActiveExternalProfiles() ) ); @@ -901,7 +898,7 @@ private void initParent( MavenProject project, Map projects, ModelBuildingResult result, ProjectBuildingRequest projectBuildingRequest ) { Model parentModel = result.getModelIds().size() > 1 && !result.getModelIds().get( 1 ).isEmpty() - ? new Model( result.getRawModel( result.getModelIds().get( 1 ) ) ) + ? result.getRawModel( result.getModelIds().get( 1 ) ) : null; if ( parentModel != null ) @@ -915,8 +912,7 @@ private void initParent( MavenProject project, Map projects, // org.apache.maven.its.mng4834:parent:0.1 String parentModelId = result.getModelIds().get( 1 ); - Path parentPomPath = result.getRawModel( parentModelId ).getPomFile(); - File parentPomFile = parentPomPath != null ? parentPomPath.toFile() : null; + File parentPomFile = result.getRawModel( parentModelId ).getPomFile(); MavenProject parent = projects.get( parentPomFile ); if ( parent == null && buildParentIfNotExisting ) { @@ -986,7 +982,7 @@ private static String inheritedGroupId( final ModelBuildingResult result, final if ( !modelId.isEmpty() ) { - final Model model = new Model( result.getRawModel( modelId ) ); + final Model model = result.getRawModel( modelId ); groupId = model.getGroupId() != null ? model.getGroupId() : inheritedGroupId( result, modelIndex + 1 ); diff --git a/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java b/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java index a962cc18fe1e..50506239fb99 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java +++ b/maven-core/src/test/java/org/apache/maven/internal/aether/ConsumerModelSourceTransformerTest.java @@ -24,7 +24,7 @@ import java.nio.file.Path; import java.nio.file.Paths; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.building.TransformerContext; import org.junit.jupiter.api.Test; import org.xmlunit.assertj.XmlAssert; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java index b830132f3531..e4154612817b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultBuildPomXMLFilterFactory.java @@ -25,7 +25,7 @@ import java.util.function.BiFunction; import java.util.function.Function; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.transform.BuildToRawPomXMLFilterFactory; import org.apache.maven.model.transform.RelativeProject; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 2959361273b2..89c5e9b5f032 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -19,9 +19,8 @@ * under the License. */ -import javax.inject.Inject; -import javax.inject.Named; -import javax.inject.Singleton; +import static org.apache.maven.model.building.Result.error; +import static org.apache.maven.model.building.Result.newResult; import java.io.File; import java.io.IOException; @@ -33,6 +32,7 @@ import java.util.Collections; import java.util.HashMap; import java.util.HashSet; +import java.util.Iterator; import java.util.LinkedHashSet; import java.util.List; import java.util.Map; @@ -40,26 +40,29 @@ import java.util.Properties; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; -import java.util.concurrent.atomic.AtomicReference; - -import org.apache.maven.api.model.Activation; -import org.apache.maven.api.model.ActivationFile; -import org.apache.maven.api.model.Build; -import org.apache.maven.api.model.Dependency; -import org.apache.maven.api.model.DependencyManagement; -import org.apache.maven.api.model.InputLocation; -import org.apache.maven.api.model.InputSource; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Parent; -import org.apache.maven.api.model.Plugin; -import org.apache.maven.api.model.PluginManagement; -import org.apache.maven.api.model.Profile; -import org.apache.maven.api.model.Repository; + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + import org.apache.maven.artifact.versioning.DefaultArtifactVersion; import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; import org.apache.maven.artifact.versioning.VersionRange; import org.apache.maven.building.Source; import org.apache.maven.feature.Features; +import org.apache.maven.model.Activation; +import org.apache.maven.model.ActivationFile; +import org.apache.maven.model.Build; +import org.apache.maven.model.Dependency; +import org.apache.maven.model.DependencyManagement; +import org.apache.maven.model.InputLocation; +import org.apache.maven.api.model.InputSource; +import org.apache.maven.model.Model; +import org.apache.maven.model.Parent; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginManagement; +import org.apache.maven.model.Profile; +import org.apache.maven.model.Repository; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.composition.DependencyManagementImporter; @@ -94,19 +97,15 @@ import org.codehaus.plexus.interpolation.StringSearchInterpolator; import org.eclipse.sisu.Nullable; -import static org.apache.maven.model.building.Result.error; -import static org.apache.maven.model.building.Result.newResult; - /** * @author Benjamin Bentmann */ @Named @Singleton -@SuppressWarnings( {"checkstyle:JavaDocMethod", "checkstyle:HiddenField", "checkstyle:ParameterNumber" } ) public class DefaultModelBuilder - implements ModelBuilder + implements ModelBuilder { - private final MavenMerger mavenMerger = new FileToRawModelMerger(); + private final MavenMerger modelMerger = new FileToRawModelMerger(); private final ModelProcessor modelProcessor; private final ModelValidator modelValidator; @@ -128,6 +127,7 @@ public class DefaultModelBuilder private final ProfileActivationFilePathInterpolator profileActivationFilePathInterpolator; private final ModelVersionProcessor versionProcessor; + @SuppressWarnings( "checkstyle:ParameterNumber" ) @Inject public DefaultModelBuilder( ModelProcessor modelProcessor, @@ -450,11 +450,11 @@ protected ModelBuildingResult build( ModelBuildingRequest request, Collection interpolatedActivations = getProfileActivations( inputModel ); - inputModel = injectProfileActivations( inputModel, interpolatedActivations ); + Map interpolatedActivations = getProfileActivations( inputModel, false ); + injectProfileActivations( inputModel, interpolatedActivations ); // profile injection for ( Profile activeProfile : activePomProfiles ) { - inputModel = profileInjector.injectProfile( inputModel, activeProfile, request, problems ); + profileInjector.injectProfile( inputModel, activeProfile, request, problems ); } for ( Profile activeProfile : activeExternalProfiles ) { - inputModel = profileInjector.injectProfile( inputModel, activeProfile, request, problems ); + profileInjector.injectProfile( inputModel, activeProfile, request, problems ); } - - return inputModel; } @SuppressWarnings( "checkstyle:methodlength" ) @@ -566,39 +565,39 @@ private Model readEffectiveModel( final ModelBuildingRequest request, final Defa profileActivationContext, problems ); result.setActivePomProfiles( modelId, activePomProfiles ); - Model tmpModel = rawModel; + Model tmpModel = rawModel.clone(); problems.setSource( tmpModel ); // model normalization - tmpModel = modelNormalizer.mergeDuplicates( tmpModel, request, problems ); + tmpModel = new Model( modelNormalizer.mergeDuplicates( tmpModel.getDelegate(), request, problems ) ); profileActivationContext.setProjectProperties( tmpModel.getProperties() ); Map interpolatedActivations = getInterpolatedActivations( rawModel, profileActivationContext, problems ); - tmpModel = injectProfileActivations( tmpModel, interpolatedActivations ); + injectProfileActivations( tmpModel, interpolatedActivations ); // profile injection for ( Profile activeProfile : result.getActivePomProfiles( modelId ) ) { - tmpModel = profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); + profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); } if ( currentData == resultData ) { for ( Profile activeProfile : activeExternalProfiles ) { - tmpModel = profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); + profileInjector.injectProfile( tmpModel, activeProfile, request, problems ); } result.setEffectiveModel( tmpModel ); } + lineage.add( tmpModel ); + if ( currentData == superData ) { - lineage.add( tmpModel ); - break; } @@ -627,14 +626,8 @@ else if ( !parentIds.add( parentData.getId() ) ) } else { - if ( !Objects.equals( tmpModel.getParent().getVersion(), parentData.getVersion() ) ) - { -// tmpModel = tmpModel.withParent( tmpModel.getParent().withVersion( parentData.getVersion() ) ); - } currentData = parentData; } - - lineage.add( tmpModel ); } problems.setSource( result.getRawModel() ); @@ -652,7 +645,7 @@ else if ( !parentIds.add( parentData.getId() ) ) resultModel = interpolateModel( resultModel, request, problems ); // url normalization - resultModel = modelUrlNormalizer.normalize( resultModel, request ); + modelUrlNormalizer.normalize( resultModel, request ); result.setEffectiveModel( resultModel ); @@ -666,23 +659,19 @@ private Map getInterpolatedActivations( Model rawModel, DefaultProfileActivationContext context, DefaultModelProblemCollector problems ) { - Map interpolatedActivations = getProfileActivations( rawModel ); - for ( Map.Entry entry : interpolatedActivations.entrySet() ) + Map interpolatedActivations = getProfileActivations( rawModel, true ); + for ( Activation activation : interpolatedActivations.values() ) { - Activation activation = entry.getValue(); if ( activation.getFile() != null ) { - Activation value = activation.withFile( - replaceWithInterpolatedValue( activation.getFile(), context, problems ) ); - entry.setValue( value ); + replaceWithInterpolatedValue( activation.getFile(), context, problems ); } } return interpolatedActivations; } - private ActivationFile replaceWithInterpolatedValue( ActivationFile activationFile, - ProfileActivationContext context, - DefaultModelProblemCollector problems ) + private void replaceWithInterpolatedValue( ActivationFile activationFile, ProfileActivationContext context, + DefaultModelProblemCollector problems ) { try { @@ -690,13 +679,13 @@ private ActivationFile replaceWithInterpolatedValue( ActivationFile activationFi { String path = activationFile.getExists(); String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context ); - return activationFile.withExists( absolutePath ); + activationFile.setExists( absolutePath ); } else if ( isNotEmpty( activationFile.getMissing() ) ) { String path = activationFile.getMissing(); String absolutePath = profileActivationFilePathInterpolator.interpolate( path, context ); - return activationFile.withMissing( absolutePath ); + activationFile.setMissing( absolutePath ); } } catch ( InterpolationException e ) @@ -709,7 +698,6 @@ else if ( isNotEmpty( activationFile.getMissing() ) ) activationFile.getLocation( isNotEmpty( activationFile.getExists() ) ? "exists" : "missing" ) ) .setException( e ) ); } - return activationFile; } private static boolean isNotEmpty( String string ) @@ -738,12 +726,10 @@ private ModelBuildingResult build( final ModelBuildingRequest request, final Mod problems.setRootModel( resultModel ); // model path translation - Path projectDirectory = resultModel.getProjectDirectory(); - resultModel = modelPathTranslator.alignToBaseDirectory( resultModel, - projectDirectory != null ? projectDirectory.toFile() : null, request ); + modelPathTranslator.alignToBaseDirectory( resultModel, resultModel.getProjectDirectory(), request ); // plugin management injection - resultModel = pluginManagementInjector.injectManagement( resultModel, request, problems ); + pluginManagementInjector.injectManagement( resultModel, request, problems ); fireEvent( resultModel, request, problems, ModelBuildingEventCatapult.BUILD_EXTENSIONS_ASSEMBLED ); @@ -755,34 +741,32 @@ private ModelBuildingResult build( final ModelBuildingRequest request, final Mod } // lifecycle bindings injection - resultModel = lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems ); + lifecycleBindingsInjector.injectLifecycleBindings( resultModel, request, problems ); } // dependency management import - resultModel = importDependencyManagement( resultModel, request, problems, imports ); + importDependencyManagement( resultModel, request, problems, imports ); // dependency management injection - resultModel = dependencyManagementInjector.injectManagement( resultModel, request, problems ); + dependencyManagementInjector.injectManagement( resultModel, request, problems ); - resultModel = modelNormalizer.injectDefaultValues( resultModel, request, problems ); + resultModel.update( modelNormalizer.injectDefaultValues( resultModel.getDelegate(), request, problems ) ); if ( request.isProcessPlugins() ) { // reports configuration - resultModel = reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); + reportConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); // reports conversion to decoupled site plugin - resultModel = reportingConverter.convertReporting( resultModel, request, problems ); + reportingConverter.convertReporting( resultModel, request, problems ); // plugins configuration - resultModel = pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); + pluginConfigurationExpander.expandPluginConfiguration( resultModel, request, problems ); } // effective model validation modelValidator.validateEffectiveModel( resultModel, request, problems ); - result.setEffectiveModel( resultModel ); - if ( hasModelErrors( problems ) ) { throw problems.newModelBuildingException(); @@ -826,7 +810,7 @@ private Model readFileModel( ModelBuildingRequest request, throws ModelBuildingException { ModelSource modelSource = request.getModelSource(); - Model model = fromCache( request.getModelCache(), modelSource, ModelCacheTag.FILE ); + org.apache.maven.api.model.Model model = fromCache( request.getModelCache(), modelSource, ModelCacheTag.FILE ); if ( model == null ) { model = doReadFileModel( modelSource, request, problems ); @@ -844,15 +828,15 @@ private Model readFileModel( ModelBuildingRequest request, } } - return model; + return new Model( model ); } @SuppressWarnings( "checkstyle:methodlength" ) - private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest request, - DefaultModelProblemCollector problems ) + private org.apache.maven.api.model.Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest request, + DefaultModelProblemCollector problems ) throws ModelBuildingException { - Model model; + org.apache.maven.api.model.Model model; problems.setSource( modelSource.getLocation() ); try { @@ -865,8 +849,8 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req InputSource source; if ( request.isLocationTracking() ) { - source = (InputSource) options.computeIfAbsent( ModelProcessor.INPUT_SOURCE, - k -> new InputSource( null, modelSource.getLocation() ) ); + source = new InputSource( null, modelSource.getLocation() ); + options.put( ModelProcessor.INPUT_SOURCE, source ); } else { @@ -946,11 +930,14 @@ private Model doReadFileModel( ModelSource modelSource, ModelBuildingRequest req if ( modelSource instanceof FileModelSource ) { - model = Model.newBuilder( model ).pomFile( ( (FileModelSource) modelSource ).getFile().toPath() ).build(); + model = model.withPomFile( ( (FileModelSource) modelSource ).getFile().toPath() ); } - problems.setSource( model ); - modelValidator.validateFileModel( model, request, problems ); + Model retModel = new Model( model ); + + problems.setSource( retModel ); + + modelValidator.validateFileModel( retModel, request, problems ); if ( hasFatalErrors( problems ) ) { @@ -987,13 +974,14 @@ private Model readRawModel( ModelBuildingRequest request, DefaultModelProblemCol try { // must implement TransformContext, but should use request to access system properties/modelcache - Model transformedFileModel = modelProcessor.read( pomFile, - Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, context ) ); + org.apache.maven.api.model.Model transformedFileModel = modelProcessor.read( pomFile, + Collections.singletonMap( ModelReader.TRANSFORMER_CONTEXT, context ) ); // rawModel with locationTrackers, required for proper feedback during validations // Apply enriched data - rawModel = mavenMerger.merge( rawModel, transformedFileModel, false, null ); + rawModel = new Model( modelMerger.merge( rawModel.getDelegate(), + transformedFileModel, false, null ) ); } catch ( IOException e ) { @@ -1006,7 +994,7 @@ else if ( request.getFileModel() == null ) } else { - rawModel = request.getFileModel(); + rawModel = request.getFileModel().clone(); } modelValidator.validateRawModel( rawModel, request, problems ); @@ -1027,6 +1015,11 @@ else if ( request.getFileModel() == null ) } private String getGroupId( Model model ) + { + return getGroupId( model.getDelegate() ); + } + + private String getGroupId( org.apache.maven.api.model.Model model ) { String groupId = model.getGroupId(); if ( groupId == null && model.getParent() != null ) @@ -1080,21 +1073,13 @@ private void configureResolver( ModelResolver modelResolver, Model model, Defaul { try { - try - { - modelResolver.addRepository( repository, replaceRepositories ); - } - catch ( AbstractMethodError e ) - { - modelResolver.addRepository( new org.apache.maven.model.Repository( repository ), - replaceRepositories ); - } + modelResolver.addRepository( repository, replaceRepositories ); } catch ( InvalidRepositoryException e ) { problems.add( new ModelProblemCollectorRequest( Severity.ERROR, Version.BASE ) - .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() ) - .setLocation( repository.getLocation( "" ) ).setException( e ) ); + .setMessage( "Invalid repository " + repository.getId() + ": " + e.getMessage() ) + .setLocation( repository.getLocation( "" ) ).setException( e ) ); } } } @@ -1154,16 +1139,16 @@ private void checkPluginVersions( List lineage, ModelBuildingRequest requ private Model assembleInheritance( List lineage, ModelBuildingRequest request, ModelProblemCollector problems ) { - Model parent = lineage.get( lineage.size() - 1 ); + org.apache.maven.api.model.Model parent = lineage.get( lineage.size() - 1 ).getDelegate(); for ( int i = lineage.size() - 2; i >= 0; i-- ) { Model child = lineage.get( i ); - parent = inheritanceAssembler.assembleModelInheritance( child, parent, request, problems ); + parent = inheritanceAssembler.assembleModelInheritance( child.getDelegate(), parent, request, problems ); } - return parent; + return new Model( parent ); } - private Map getProfileActivations( Model model ) + private Map getProfileActivations( Model model, boolean clone ) { Map activations = new HashMap<>(); for ( Profile profile : model.getProfiles() ) @@ -1175,15 +1160,19 @@ private Map getProfileActivations( Model model ) continue; } + if ( clone ) + { + activation = activation.clone(); + } + activations.put( profile.getId(), activation ); } return activations; } - private Model injectProfileActivations( Model model, Map activations ) + private void injectProfileActivations( Model model, Map activations ) { - List newProfiles = null; for ( Profile profile : model.getProfiles() ) { Activation activation = profile.getActivation(); @@ -1194,66 +1183,44 @@ private Model injectProfileActivations( Model model, Map act } // restore activation - if ( newProfiles == null ) - { - newProfiles = new ArrayList<>( model.getProfiles() ); - } - int idx = model.getProfiles().indexOf( profile ); - Profile newProfile = Profile.newBuilder( profile ). - activation( activations.get( profile.getId() ) ).build(); - newProfiles.set( idx, newProfile ); + profile.setActivation( activations.get( profile.getId() ) ); } - return Model.newBuilder( model ).profiles( newProfiles ).build(); } private Model interpolateModel( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { // save profile activations before interpolation, since they are evaluated with limited scope - Map originalActivations = getProfileActivations( model ); + Map originalActivations = getProfileActivations( model, true ); - // Overwrite existing values in model properties. Otherwise it's not possible - // to define the version via command line: mvn -Drevision=6.5.7 ... - Properties props = new Properties(); - props.putAll( model.getProperties() ); - versionProcessor.overwriteModelProperties( props, request ); - if ( !props.equals( model.getProperties() ) ) - { - model = model.withProperties( props ); - } - - Path projectDir = model.getProjectDirectory(); - Model interpolatedModel = modelInterpolator.interpolateModel( - model, projectDir != null ? projectDir.toFile() : null, request, problems ); + Model interpolatedModel = new Model( modelInterpolator.interpolateModel( + model.getDelegate(), model.getProjectDirectory(), request, problems ) ); if ( interpolatedModel.getParent() != null ) { StringSearchInterpolator ssi = new StringSearchInterpolator(); ssi.addValueSource( new MapBasedValueSource( request.getUserProperties() ) ); + ssi.addValueSource( new MapBasedValueSource( model.getProperties() ) ); + ssi.addValueSource( new MapBasedValueSource( request.getSystemProperties() ) ); try { - String parentVersion = interpolatedModel.getParent().getVersion(); - - String interpolated = ssi.interpolate( parentVersion ); - - if ( !parentVersion.equals( interpolated ) ) - { - interpolatedModel = interpolatedModel.withParent( - interpolatedModel.getParent().withVersion( interpolated ) ); - } + String interpolated = ssi.interpolate( interpolatedModel.getParent().getVersion() ); + interpolatedModel.getParent().setVersion( interpolated ); } catch ( Exception e ) { ModelProblemCollectorRequest mpcr = - new ModelProblemCollectorRequest( Severity.ERROR, - Version.BASE ).setMessage( "Failed to interpolate field: " - + interpolatedModel.getParent().getVersion() - + " on class: " ).setException( e ); + new ModelProblemCollectorRequest( Severity.ERROR, + Version.BASE ).setMessage( "Failed to interpolate field: " + + interpolatedModel.getParent().getVersion() + + " on class: " ).setException( e ); problems.add( mpcr ); } + + } - interpolatedModel = interpolatedModel.withPomFile( model.getPomFile() ); + interpolatedModel.setPomFile( model.getPomFile() ); // restore profiles with file activation to their value before full interpolation injectProfileActivations( model, originalActivations ); @@ -1328,7 +1295,7 @@ private ModelData readParentLocally( Model childModel, Source childSource, Model { return null; } - candidateSource = new FileModelSource( candidateModel.getPomFile().toFile() ); + candidateSource = new FileModelSource( candidateModel.getPomFile() ); } // @@ -1463,10 +1430,9 @@ private ModelData readParentExternally( Model childModel, ModelBuildingRequest r ModelProblemUtils.toSourceHint( childModel ) ) ); ModelSource modelSource; - AtomicReference modified = new AtomicReference<>(); try { - modelSource = modelResolver.resolveModel( parent, modified ); + modelSource = modelResolver.resolveModel( parent ); } catch ( UnresolvableModelException e ) { @@ -1499,12 +1465,6 @@ private ModelData readParentExternally( Model childModel, ModelBuildingRequest r throw problems.newModelBuildingException(); } - if ( modified.get() != null ) - { - parent = modified.get(); - childModel = childModel.withParent( parent ); - } - int validationLevel = Math.min( request.getValidationLevel(), ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_2_0 ); ModelBuildingRequest lenientRequest = new DefaultModelBuildingRequest( request ) .setValidationLevel( validationLevel ) @@ -1545,51 +1505,38 @@ private ModelData readParentExternally( Model childModel, ModelBuildingRequest r private Model getSuperModel() { - return superPomProvider.getSuperModel( "4.0.0" ); + return new Model( superPomProvider.getSuperModel( "4.0.0" ) ); } - private Model importDependencyManagement( Model model, ModelBuildingRequest request, + private void importDependencyManagement( Model model, ModelBuildingRequest request, DefaultModelProblemCollector problems, Collection importIds ) { DependencyManagement depMgmt = model.getDependencyManagement(); if ( depMgmt == null ) { - return model; + return; } String importing = model.getGroupId() + ':' + model.getArtifactId() + ':' + model.getVersion(); importIds.add( importing ); - List importMgmts = null; + List importMgmts = null; - List newDependencies = null; - - for ( Dependency dependency : depMgmt.getDependencies() ) + for ( Iterator it = depMgmt.getDependencies().iterator(); it.hasNext(); ) { + Dependency dependency = it.next(); + if ( !"pom".equals( dependency.getType() ) || !"import".equals( dependency.getScope() ) ) { continue; } - if ( newDependencies == null ) - { - newDependencies = new ArrayList<>( depMgmt.getDependencies() ); - } - newDependencies.remove( dependency ); - - AtomicReference resolvedDependency = new AtomicReference<>(); + it.remove(); DependencyManagement importMgmt = loadDependencyManagement( model, request, problems, - dependency, importIds, resolvedDependency ); - - if ( resolvedDependency.get() != null ) - { - // TODO: The dependency for the BOM has been resolved, but we are actually getting rid of it... - // Before the introduction of the immutable model, the dependency was updated. - Dependency resolvedDep = resolvedDependency.get(); - } + dependency, importIds ); if ( importMgmt != null ) { @@ -1598,25 +1545,20 @@ private Model importDependencyManagement( Model model, ModelBuildingRequest requ importMgmts = new ArrayList<>(); } - importMgmts.add( importMgmt ); + importMgmts.add( importMgmt.getDelegate() ); } } - if ( newDependencies != null ) - { - model = model.withDependencyManagement( depMgmt.withDependencies( newDependencies ) ); - } - importIds.remove( importing ); - return dependencyManagementImporter.importManagement( model, importMgmts, request, problems ); + model.update( dependencyManagementImporter.importManagement( + model.getDelegate(), importMgmts, request, problems ) ); } private DependencyManagement loadDependencyManagement( Model model, ModelBuildingRequest request, DefaultModelProblemCollector problems, Dependency dependency, - Collection importIds, - AtomicReference resolvedDependency ) + Collection importIds ) { String groupId = dependency.getGroupId(); String artifactId = dependency.getArtifactId(); @@ -1664,19 +1606,21 @@ private DependencyManagement loadDependencyManagement( Model model, ModelBuildin return null; } - DependencyManagement importMgmt = fromCache( request.getModelCache(), groupId, artifactId, version, - ModelCacheTag.IMPORT ); + org.apache.maven.api.model.DependencyManagement importMgmt = + fromCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT ); if ( importMgmt == null ) { - importMgmt = doLoadDependencyManagement( model, request, problems, dependency, - groupId, artifactId, version, importIds, resolvedDependency ); - if ( importMgmt != null ) + DependencyManagement importMgmtV3 = doLoadDependencyManagement( model, request, problems, dependency, + groupId, artifactId, version, importIds ); + if ( importMgmtV3 != null ) { - intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, importMgmt ); + importMgmt = importMgmtV3.getDelegate(); + intoCache( request.getModelCache(), groupId, artifactId, version, ModelCacheTag.IMPORT, + importMgmt ); } } - return importMgmt; + return importMgmt != null ? new DependencyManagement( importMgmt ) : null; } @SuppressWarnings( "checkstyle:parameternumber" ) @@ -1686,8 +1630,7 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild String groupId, String artifactId, String version, - Collection importIds, - AtomicReference resolvedDependency ) + Collection importIds ) { DependencyManagement importMgmt; final WorkspaceModelResolver workspaceResolver = request.getWorkspaceModelResolver(); @@ -1721,7 +1664,7 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild final ModelSource importSource; try { - importSource = modelResolver.resolveModel( dependency, resolvedDependency ); + importSource = modelResolver.resolveModel( dependency ); } catch ( UnresolvableModelException e ) { @@ -1769,7 +1712,7 @@ private DependencyManagement doLoadDependencyManagement( Model model, ModelBuild if ( importMgmt == null ) { - importMgmt = DependencyManagement.newInstance(); + importMgmt = new DependencyManagement(); } return importMgmt; } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java index 5d0a159f2845..397e1c6992da 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilderFactory.java @@ -21,7 +21,7 @@ import java.util.Arrays; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.composition.DefaultDependencyManagementImporter; import org.apache.maven.model.composition.DependencyManagementImporter; import org.apache.maven.model.inheritance.DefaultInheritanceAssembler; @@ -388,11 +388,10 @@ private static class StubLifecycleBindingsInjector { @Override - public Model injectLifecycleBindings( Model model, - ModelBuildingRequest request, - ModelProblemCollector problems ) + public void injectLifecycleBindings( Model model, + ModelBuildingRequest request, + ModelProblemCollector problems ) { - return model; } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java index 3d21c238486f..c88df754754d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingEvent.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Holds data relevant for a model building event. @@ -30,7 +30,7 @@ class DefaultModelBuildingEvent implements ModelBuildingEvent { - private final Model model; + private Model model; private final ModelBuildingRequest request; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java index 2ae68ec4adf4..379b5e7e1c2c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingRequest.java @@ -25,8 +25,8 @@ import java.util.List; import java.util.Properties; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.WorkspaceModelResolver; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java index a4e9113eda50..b2fcfa05f02d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuildingResult.java @@ -25,8 +25,8 @@ import java.util.Map; import java.util.Objects; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; /** * Collects the output of the model builder. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java index c2807a457dc7..95c71c57190c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblem.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Describes a problem that was encountered during model building. A problem can either be an exception that was thrown diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java index 4cd9278d60df..c06869a80de9 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelProblemCollector.java @@ -23,7 +23,7 @@ import java.util.List; import java.util.Set; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.io.ModelParseException; /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java index 2e4ebe62f977..3c70b3c9af03 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultTransformerContext.java @@ -25,7 +25,7 @@ import java.util.concurrent.ConcurrentHashMap; import java.util.function.Supplier; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java index c9bf1e173bb1..d12a89a420b1 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/FilterModelBuildingRequest.java @@ -24,8 +24,8 @@ import java.util.List; import java.util.Properties; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.WorkspaceModelResolver; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java index 414fccb30e96..74c1fa6c311b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuilder.java @@ -21,7 +21,7 @@ import java.io.File; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Builds the effective model from a POM. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java index f3920e92617c..2995b1bfb1e7 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingEvent.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Holds data relevant for a model building event. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java index 7227c7a2fd49..e9d18e456d34 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingException.java @@ -24,7 +24,7 @@ import java.util.Collections; import java.util.List; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Signals one ore more errors during model building. The model builder tries to collect as many problems as possible diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java index 157bf5cba6ba..9cdb06cb1db1 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingRequest.java @@ -24,8 +24,8 @@ import java.util.List; import java.util.Properties; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.WorkspaceModelResolver; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java index e5fecedf4e28..603d2140ad9b 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelBuildingResult.java @@ -21,8 +21,8 @@ import java.util.List; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; /** * Collects the output of the model builder. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java index ce74df2c7526..1ef4341a8e9c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelData.java @@ -22,7 +22,7 @@ import java.util.Objects; import org.apache.maven.building.Source; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Holds a model along with some auxiliary information. This internal utility class assists the model builder during POM diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java index 430e406f45b9..8edab3c01d29 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemCollectorRequest.java @@ -21,7 +21,7 @@ import java.util.Objects; -import org.apache.maven.api.model.InputLocation; +import org.apache.maven.model.InputLocation; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java index f946c17ed7d3..d853503ee155 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/ModelProblemUtils.java @@ -19,9 +19,9 @@ * under the License. */ -import java.nio.file.Path; +import java.io.File; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Assists in the handling of model problems. @@ -48,7 +48,7 @@ static String toSourceHint( Model model ) buffer.append( toId( model ) ); - Path pomFile = model.getPomFile(); + File pomFile = model.getPomFile(); if ( pomFile != null ) { buffer.append( " (" ).append( pomFile ).append( ')' ); @@ -63,11 +63,11 @@ static String toPath( Model model ) if ( model != null ) { - Path pomFile = model.getPomFile(); + File pomFile = model.getPomFile(); if ( pomFile != null ) { - path = pomFile.toAbsolutePath().toString(); + path = pomFile.getAbsolutePath(); } } @@ -80,7 +80,11 @@ static String toId( Model model ) { return ""; } + return toId( model.getDelegate() ); + } + static String toId( org.apache.maven.api.model.Model model ) + { String groupId = model.getGroupId(); if ( groupId == null && model.getParent() != null ) { diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java index 0d3ca8b743f3..e041af4912db 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/TransformerContext.java @@ -21,7 +21,7 @@ import java.nio.file.Path; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * Context used to transform a pom file. diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java index 82e27cb88b9d..4228f83531f1 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/interpolation/AbstractStringBasedModelInterpolator.java @@ -86,6 +86,14 @@ public AbstractStringBasedModelInterpolator( PathTranslator pathTranslator, UrlN this.urlNormalizer = urlNormalizer; } + @Override + public org.apache.maven.model.Model interpolateModel( org.apache.maven.model.Model model, File projectDir, + ModelBuildingRequest request, ModelProblemCollector problems ) + { + return new org.apache.maven.model.Model( interpolateModel( model.getDelegate(), projectDir, + request, problems ) ); + } + protected List createValueSources( final Model model, final File projectDir, final ModelBuildingRequest config, final ModelProblemCollector problems ) 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 dbb9780c7da1..25de5ef939c5 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 @@ -49,4 +49,7 @@ 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, File projectDir, + ModelBuildingRequest request, ModelProblemCollector problems ); + } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java index 57edccf3bb63..568dfac197a3 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelReader.java @@ -109,6 +109,11 @@ private boolean isStrict( Map options ) private InputSource getSource( Map options ) { Object value = ( options != null ) ? options.get( INPUT_SOURCE ) : null; + if ( value instanceof org.apache.maven.model.InputSource ) + { + org.apache.maven.model.InputSource src = ( org.apache.maven.model.InputSource ) value; + return new InputSource( src.getModelId(), src.getLocation() ); + } return (InputSource) value; } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java index 9b2fb4c2e840..17c0b236a445 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultDependencyManagementInjector.java @@ -51,9 +51,10 @@ public class DefaultDependencyManagementInjector private ManagementModelMerger merger = new ManagementModelMerger(); @Override - public Model injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void injectManagement( org.apache.maven.model.Model model, ModelBuildingRequest request, + ModelProblemCollector problems ) { - return merger.mergeManagedDependencies( model ); + model.update( merger.mergeManagedDependencies( model.getDelegate() ) ); } /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java index 62e3226f5342..0b21a3b7c2dc 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DefaultPluginManagementInjector.java @@ -53,9 +53,10 @@ public class DefaultPluginManagementInjector private ManagementModelMerger merger = new ManagementModelMerger(); @Override - public Model injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void injectManagement( org.apache.maven.model.Model model, ModelBuildingRequest request, + ModelProblemCollector problems ) { - return merger.mergeManagedBuildPlugins( model ); + model.update( merger.mergeManagedBuildPlugins( model.getDelegate() ) ); } /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java index 0b3e5277ba4f..3b70a09c9703 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/DependencyManagementInjector.java @@ -19,7 +19,7 @@ * under the License. */ -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; @@ -39,6 +39,6 @@ public interface DependencyManagementInjector * @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 injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java index 6b508ff96232..7384fdf045f2 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/management/PluginManagementInjector.java @@ -19,7 +19,7 @@ * under the License. */ -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; @@ -39,6 +39,6 @@ public interface PluginManagementInjector * @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 injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + void injectManagement( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java index 2c9b5b1ce347..2afe21f51b9a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelPathTranslator.java @@ -55,13 +55,14 @@ public DefaultModelPathTranslator( PathTranslator pathTranslator ) } @Override - public Model alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ) + public void alignToBaseDirectory( org.apache.maven.model.Model modelV3, File basedir, ModelBuildingRequest request ) { - if ( model == null || basedir == null ) + if ( modelV3 == null || basedir == null ) { - return model; + return; } + Model model = modelV3.getDelegate(); Build build = model.getBuild(); Build newBuild = null; if ( build != null ) @@ -89,12 +90,11 @@ public Model alignToBaseDirectory( Model model, File basedir, ModelBuildingReque } if ( newBuild != build || newReporting != reporting ) { - return Model.newBuilder( model ) + modelV3.update( Model.newBuilder( model ) .build( newBuild ) .reporting( newReporting ) - .build(); + .build() ); } - return model; } private List map( List resources, Function mapper ) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java index 58a7fbd9097b..b3770b3588a4 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/DefaultModelUrlNormalizer.java @@ -23,12 +23,10 @@ import javax.inject.Named; import javax.inject.Singleton; -import java.util.Objects; - -import org.apache.maven.api.model.DistributionManagement; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Scm; -import org.apache.maven.api.model.Site; +import org.apache.maven.model.DistributionManagement; +import org.apache.maven.model.Model; +import org.apache.maven.model.Scm; +import org.apache.maven.model.Site; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -40,7 +38,7 @@ @Named @Singleton public class DefaultModelUrlNormalizer - implements ModelUrlNormalizer + implements ModelUrlNormalizer { private final UrlNormalizer urlNormalizer; @@ -52,29 +50,21 @@ public DefaultModelUrlNormalizer( UrlNormalizer urlNormalizer ) } @Override - public Model normalize( Model model, ModelBuildingRequest request ) + public void normalize( Model model, ModelBuildingRequest request ) { if ( model == null ) { - return null; + return; } - Model.Builder builder = Model.newBuilder( model ); - - builder.url( normalize( model.getUrl() ) ); + model.setUrl( normalize( model.getUrl() ) ); Scm scm = model.getScm(); if ( scm != null ) { - scm = Scm.newBuilder( scm ) - .url( normalize( scm.getUrl() ) ) - .connection( normalize( scm.getConnection() ) ) - .developerConnection( normalize( scm.getDeveloperConnection() ) ) - .build(); - if ( scm != model.getScm() ) - { - builder.scm( scm ); - } + scm.setUrl( normalize( scm.getUrl() ) ); + scm.setConnection( normalize( scm.getConnection() ) ); + scm.setDeveloperConnection( normalize( scm.getDeveloperConnection() ) ); } DistributionManagement dist = model.getDistributionManagement(); @@ -83,23 +73,14 @@ public Model normalize( Model model, ModelBuildingRequest request ) Site site = dist.getSite(); if ( site != null ) { - site = Site.newBuilder( site ) - .url( normalize( site.getUrl() ) ) - .build(); - if ( site != dist.getSite() ) - { - builder.distributionManagement( dist.withSite( site ) ); - } + site.setUrl( normalize( site.getUrl() ) ); } } - - return builder.build(); } private String normalize( String url ) { - String newUrl = urlNormalizer.normalize( url ); - return Objects.equals( url, newUrl ) ? null : newUrl; + return urlNormalizer.normalize( url ); } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java index 1d73a591257a..2bd39c5501ff 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelPathTranslator.java @@ -21,7 +21,7 @@ import java.io.File; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -40,6 +40,6 @@ public interface ModelPathTranslator * @param basedir The base directory to resolve relative paths against, may be {@code null}. * @param request The model building request that holds further settings, must not be {@code null}. */ - Model alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ); + void alignToBaseDirectory( Model model, File basedir, ModelBuildingRequest request ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java index 33b2998cdb01..8325b05d35f4 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/path/ModelUrlNormalizer.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; /** @@ -37,6 +37,6 @@ public interface ModelUrlNormalizer * @param model The model whose URLs should be normalized, may be {@code null}. * @param request The model building request that holds further settings, must not be {@code null}. */ - Model normalize( Model model, ModelBuildingRequest request ); + void normalize( Model model, ModelBuildingRequest request ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java index 3395234fb1cf..69d44bc192da 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultPluginConfigurationExpander.java @@ -19,20 +19,19 @@ * under the License. */ -import java.util.ArrayList; import java.util.List; import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.api.xml.Dom; -import org.apache.maven.api.model.Build; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Plugin; -import org.apache.maven.api.model.PluginExecution; -import org.apache.maven.api.model.PluginManagement; +import org.apache.maven.model.Build; +import org.apache.maven.model.Model; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginExecution; +import org.apache.maven.model.PluginManagement; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; +import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Handles expansion of general build plugin configuration into individual executions. @@ -42,57 +41,46 @@ @Named @Singleton public class DefaultPluginConfigurationExpander - implements PluginConfigurationExpander + implements PluginConfigurationExpander { @Override - public Model expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { Build build = model.getBuild(); if ( build != null ) { - Build.Builder builder = Build.newBuilder( build ); - - builder.plugins( expand( build.getPlugins() ) ); + expand( build.getPlugins() ); PluginManagement pluginManagement = build.getPluginManagement(); if ( pluginManagement != null ) { - builder.pluginManagement( pluginManagement.withPlugins( expand( pluginManagement.getPlugins() ) ) ); + expand( pluginManagement.getPlugins() ); } - - return model.withBuild( builder.build() ); } - - return model; } - private List expand( List plugins ) + private void expand( List plugins ) { - List newPlugins = new ArrayList<>( plugins.size() ); - for ( Plugin plugin : plugins ) { - Dom parentDom = plugin.getConfiguration(); + Xpp3Dom pluginConfiguration = (Xpp3Dom) plugin.getConfiguration(); - if ( parentDom != null ) + if ( pluginConfiguration != null ) { - List executions = new ArrayList<>( plugin.getExecutions().size() ); for ( PluginExecution execution : plugin.getExecutions() ) { - Dom childDom = execution.getConfiguration(); - executions.add( execution.withConfiguration( - childDom != null ? childDom.merge( parentDom ) : parentDom ) ); + Xpp3Dom executionConfiguration = (Xpp3Dom) execution.getConfiguration(); + + executionConfiguration = + Xpp3Dom.mergeXpp3Dom( executionConfiguration, new Xpp3Dom( pluginConfiguration ) ); + + execution.setConfiguration( executionConfiguration ); } - plugin = plugin.withExecutions( executions ); } - - newPlugins.add( plugin ); } - - return newPlugins; } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java index a6fcef68c334..044ec351f7b8 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportConfigurationExpander.java @@ -22,16 +22,13 @@ import javax.inject.Named; import javax.inject.Singleton; -import java.util.ArrayList; -import java.util.List; - -import org.apache.maven.api.xml.Dom; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.ReportPlugin; -import org.apache.maven.api.model.ReportSet; -import org.apache.maven.api.model.Reporting; +import org.apache.maven.model.Model; +import org.apache.maven.model.ReportPlugin; +import org.apache.maven.model.ReportSet; +import org.apache.maven.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; +import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Handles expansion of general report plugin configuration into individual report sets. @@ -41,37 +38,31 @@ @Named @Singleton public class DefaultReportConfigurationExpander - implements ReportConfigurationExpander + implements ReportConfigurationExpander { @Override - public Model expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { Reporting reporting = model.getReporting(); if ( reporting != null ) { - List reportPlugins = new ArrayList<>(); for ( ReportPlugin reportPlugin : reporting.getPlugins() ) { - Dom parentDom = reportPlugin.getConfiguration(); + Xpp3Dom parentDom = (Xpp3Dom) reportPlugin.getConfiguration(); + if ( parentDom != null ) { - List reportSets = new ArrayList<>(); - for ( ReportSet reportSet : reportPlugin.getReportSets() ) + for ( ReportSet execution : reportPlugin.getReportSets() ) { - Dom childDom = reportSet.getConfiguration(); - Dom newDom = childDom != null ? childDom.merge( parentDom ) : parentDom; - reportSets.add( reportSet.withConfiguration( newDom ) ); + Xpp3Dom childDom = (Xpp3Dom) execution.getConfiguration(); + childDom = Xpp3Dom.mergeXpp3Dom( childDom, new Xpp3Dom( parentDom ) ); + execution.setConfiguration( childDom ); } - reportPlugin = reportPlugin.withReportSets( reportSets ); } - reportPlugins.add( reportPlugin ); } - return model.withReporting( reporting.withPlugins( reportPlugins ) ); } - - return model; } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java index fa6b64f1cba8..75a8443e2f58 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/DefaultReportingConverter.java @@ -22,27 +22,22 @@ import javax.inject.Named; import javax.inject.Singleton; -import java.util.ArrayList; -import java.util.Arrays; -import java.util.Collections; -import java.util.List; - -import org.apache.maven.api.xml.Dom; -import org.apache.maven.internal.xml.Xpp3Dom; -import org.apache.maven.api.model.Build; -import org.apache.maven.api.model.InputLocation; -import org.apache.maven.api.model.InputSource; -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Plugin; -import org.apache.maven.api.model.PluginManagement; -import org.apache.maven.api.model.ReportPlugin; -import org.apache.maven.api.model.ReportSet; -import org.apache.maven.api.model.Reporting; +import org.apache.maven.model.Build; +import org.apache.maven.model.InputLocation; +import org.apache.maven.model.InputSource; +import org.apache.maven.model.Model; +import org.apache.maven.model.Plugin; +import org.apache.maven.model.PluginManagement; +import org.apache.maven.model.ReportPlugin; +import org.apache.maven.model.ReportSet; +import org.apache.maven.model.Reporting; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblemCollectorRequest; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; +import org.codehaus.plexus.util.StringUtils; +import org.codehaus.plexus.util.xml.Xpp3Dom; /** * Handles conversion of the <reporting> section into the configuration of Maven Site Plugin 3.x, @@ -53,71 +48,82 @@ @Named @Singleton public class DefaultReportingConverter - implements ReportingConverter + implements ReportingConverter { private final InputLocation location; { String modelId = "org.apache.maven:maven-model-builder:" - + this.getClass().getPackage().getImplementationVersion() + ":reporting-converter"; - InputSource inputSource = new InputSource( modelId, null ); + + this.getClass().getPackage().getImplementationVersion() + ":reporting-converter"; + InputSource inputSource = new InputSource(); + inputSource.setModelId( modelId ); location = new InputLocation( -1, -1, inputSource ); + location.setLocation( 0, location ); } @Override - public Model convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) + public void convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ) { Reporting reporting = model.getReporting(); if ( reporting == null ) { - return model; + return; } - Model.Builder builder = Model.newBuilder( model ); - Build build = model.getBuild(); if ( build == null ) { - build = Build.newInstance(); - builder.location( "build", location ); + build = new Build(); + model.setBuild( build ); + model.setLocation( "build", location ); } Plugin sitePlugin = findSitePlugin( build ); + if ( sitePlugin == null ) { - sitePlugin = Plugin.newBuilder() - .artifactId( "maven-site-plugin" ) - .location( "artifactId", location ) - .build(); + sitePlugin = new Plugin(); + sitePlugin.setArtifactId( "maven-site-plugin" ); + sitePlugin.setLocation( "artifactId", location ); + PluginManagement pluginManagement = build.getPluginManagement(); + if ( pluginManagement == null ) + { + pluginManagement = new PluginManagement(); + build.setPluginManagement( pluginManagement ); + } + pluginManagement.addPlugin( sitePlugin ); } - Dom configuration = sitePlugin.getConfiguration(); + Xpp3Dom configuration = (Xpp3Dom) sitePlugin.getConfiguration(); + if ( configuration == null ) { - configuration = newDom( "", "", location ); + configuration = new Xpp3Dom( "configuration", location ); + sitePlugin.setConfiguration( configuration ); } - List configChildren = new ArrayList<>( configuration.getChildren() ); + Xpp3Dom reportPlugins = configuration.getChild( "reportPlugins" ); - if ( configuration.getChild( "reportPlugins" ) != null ) + if ( reportPlugins != null ) { // new-style report configuration already present: warn since this new style has been deprecated // in favor of classical reporting section MSITE-647 / MSITE-684 problems.add( new ModelProblemCollectorRequest( Severity.WARNING, Version.BASE ) .setMessage( "Reporting configuration should be done in section, " - + "not in maven-site-plugin as reportPlugins parameter." ) + + "not in maven-site-plugin as reportPlugins parameter." ) .setLocation( sitePlugin.getLocation( "configuration" ) ) ); - return model; + return; } if ( configuration.getChild( "outputDirectory" ) == null ) { - configChildren.add( newDom( "outputDirectory", reporting.getOutputDirectory(), - reporting.getLocation( "outputDirectory" ) ) ); + addDom( configuration, "outputDirectory", reporting.getOutputDirectory(), + reporting.getLocation( "outputDirectory" ) ); } - List reportPlugins = new ArrayList<>(); + reportPlugins = new Xpp3Dom( "reportPlugins", location ); + configuration.addChild( reportPlugins ); boolean hasMavenProjectInfoReportsPlugin = false; @@ -134,12 +140,12 @@ public Model convertReporting( Model model, ModelBuildingRequest request, ModelP for ( ReportPlugin plugin : reporting.getPlugins() ) { - Dom reportPlugin = convert( plugin ); - reportPlugins.add( reportPlugin ); + Xpp3Dom reportPlugin = convert( plugin ); + reportPlugins.addChild( reportPlugin ); if ( !reporting.isExcludeDefaults() && !hasMavenProjectInfoReportsPlugin - && "org.apache.maven.plugins".equals( plugin.getGroupId() ) - && "maven-project-info-reports-plugin".equals( plugin.getArtifactId() ) ) + && "org.apache.maven.plugins".equals( plugin.getGroupId() ) + && "maven-project-info-reports-plugin".equals( plugin.getArtifactId() ) ) { hasMavenProjectInfoReportsPlugin = true; } @@ -147,51 +153,13 @@ public Model convertReporting( Model model, ModelBuildingRequest request, ModelP if ( !reporting.isExcludeDefaults() && !hasMavenProjectInfoReportsPlugin ) { - Xpp3Dom dom = newDom( "reportPlugin", - Arrays.asList( - newDom( "groupId", "org.apache.maven.plugins", null ), - newDom( "artifactId", "maven-project-info-reports-plugin", null ) - ), - location ); - - reportPlugins.add( dom ); - } - - configChildren.add( newDom( "reportPlugins", reportPlugins, location ) ); - configuration = newDom( "configuration", configChildren, location ); + Xpp3Dom dom = new Xpp3Dom( "reportPlugin", location ); - Plugin finalSitePlugin = sitePlugin.withConfiguration( configuration ); + addDom( dom, "groupId", "org.apache.maven.plugins" ); + addDom( dom, "artifactId", "maven-project-info-reports-plugin" ); - Plugin sitePluginFromPlugins = build.getPlugins().stream() - .filter( this::isSitePlugin ).findFirst().orElse( null ); - if ( sitePluginFromPlugins != null ) - { - List plugins = new ArrayList<>( build.getPlugins() ); - plugins.replaceAll( p -> p == sitePluginFromPlugins ? finalSitePlugin : p ); - build = build.withPlugins( plugins ); - } - else if ( build.getPluginManagement() == null ) - { - build = build.withPluginManagement( PluginManagement.newBuilder() - .plugins( Collections.singletonList( finalSitePlugin ) ).build() ); - } - else - { - Plugin sitePluginFromManagement = build.getPluginManagement().getPlugins().stream() - .filter( this::isSitePlugin ).findFirst().orElse( null ); - List plugins = new ArrayList<>( build.getPluginManagement().getPlugins() ); - if ( sitePluginFromManagement != null ) - { - plugins.replaceAll( p -> p == sitePluginFromManagement ? finalSitePlugin : p ); - } - else - { - plugins.add( finalSitePlugin ); - } - build = build.withPluginManagement( build.getPluginManagement().withPlugins( plugins ) ); + reportPlugins.addChild( dom ); } - - return builder.build( build ).build(); } private Plugin findSitePlugin( Build build ) @@ -222,76 +190,85 @@ private Plugin findSitePlugin( Build build ) private boolean isSitePlugin( Plugin plugin ) { return "maven-site-plugin".equals( plugin.getArtifactId() ) - && "org.apache.maven.plugins".equals( plugin.getGroupId() ); + && "org.apache.maven.plugins".equals( plugin.getGroupId() ); } - private Dom convert( ReportPlugin plugin ) + private Xpp3Dom convert( ReportPlugin plugin ) { - List children = new ArrayList<>(); + Xpp3Dom dom = new Xpp3Dom( "reportPlugin", plugin.getLocation( "" ) ); - children.add( newDom( "groupId", plugin.getGroupId(), plugin.getLocation( "groupId" ) ) ); - children.add( newDom( "artifactId", plugin.getArtifactId(), plugin.getLocation( "artifactId" ) ) ); - children.add( newDom( "version", plugin.getVersion(), plugin.getLocation( "version" ) ) ); + addDom( dom, "groupId", plugin.getGroupId(), plugin.getLocation( "groupId" ) ); + addDom( dom, "artifactId", plugin.getArtifactId(), plugin.getLocation( "artifactId" ) ); + addDom( dom, "version", plugin.getVersion(), plugin.getLocation( "version" ) ); - Dom configuration = plugin.getConfiguration(); + Xpp3Dom configuration = (Xpp3Dom) plugin.getConfiguration(); if ( configuration != null ) { - children.add( configuration ); + configuration = new Xpp3Dom( configuration ); + dom.addChild( configuration ); } if ( !plugin.getReportSets().isEmpty() ) { - List reportSets = new ArrayList<>(); + Xpp3Dom reportSets = new Xpp3Dom( "reportSets", plugin.getLocation( "reportSets" ) ); for ( ReportSet reportSet : plugin.getReportSets() ) { - Dom rs = convert( reportSet ); - reportSets.add( rs ); + Xpp3Dom rs = convert( reportSet ); + reportSets.addChild( rs ); } - children.add( newDom( "reportSets", reportSets, plugin.getLocation( "reportSets" ) ) ); + dom.addChild( reportSets ); } - return newDom( "reportPlugin", children, plugin.getLocation( "" ) ); + return dom; } - private Dom convert( ReportSet reportSet ) + private Xpp3Dom convert( ReportSet reportSet ) { - List children = new ArrayList<>(); + Xpp3Dom dom = new Xpp3Dom( "reportSet", reportSet.getLocation( "" ) ); - if ( reportSet.getId() != null ) - { - InputLocation idLocation = reportSet.getLocation( "id" ); - children.add( newDom( "id", reportSet.getId(), idLocation == null ? location : idLocation ) ); - } + InputLocation idLocation = reportSet.getLocation( "id" ); + addDom( dom, "id", reportSet.getId(), idLocation == null ? location : idLocation ); - Dom configuration = reportSet.getConfiguration(); + Xpp3Dom configuration = (Xpp3Dom) reportSet.getConfiguration(); if ( configuration != null ) { - children.add( configuration ); + configuration = new Xpp3Dom( configuration ); + dom.addChild( configuration ); } if ( !reportSet.getReports().isEmpty() ) { InputLocation location = reportSet.getLocation( "reports" ); - List reports = new ArrayList<>(); - for ( int n = 0; n < reportSet.getReports().size(); n++ ) + Xpp3Dom reports = new Xpp3Dom( "reports", location ); + int n = 0; + for ( String report : reportSet.getReports() ) { - String report = reportSet.getReports().get( n ); - reports.add( newDom( "report", report, location != null ? location.getLocation( n ) : null ) ); + addDom( reports, "report", report, ( location == null ) ? null : location.getLocation( n++ ) ); } - children.add( newDom( "reports", reports, location ) ); + dom.addChild( reports ); } - return newDom( "reportSet", children, reportSet.getLocation( "" ) ); + return dom; } - private Xpp3Dom newDom( String name, String value, InputLocation location ) + private void addDom( Xpp3Dom parent, String childName, String childValue ) { - return new Xpp3Dom( name, value, null, null, location ); + addDom( parent, childName, childValue, location ); } - private Xpp3Dom newDom( String name, List children, InputLocation location ) + private void addDom( Xpp3Dom parent, String childName, String childValue, InputLocation location ) + { + if ( StringUtils.isNotEmpty( childValue ) ) + { + parent.addChild( newDom( childName, childValue, location ) ); + } + } + + private Xpp3Dom newDom( String name, String value, InputLocation location ) { - return new Xpp3Dom( name, null, null, children, location ); + Xpp3Dom dom = new Xpp3Dom( name, location ); + dom.setValue( value ); + return dom; } -} +} \ No newline at end of file diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java index fe5772841873..9c0f06de1eef 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/LifecycleBindingsInjector.java @@ -19,7 +19,7 @@ * under the License. */ -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; @@ -41,6 +41,6 @@ public interface LifecycleBindingsInjector * @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 injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + void injectLifecycleBindings( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java index 97209740740b..23994aa6f36e 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/PluginConfigurationExpander.java @@ -19,7 +19,7 @@ * under the License. */ -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; @@ -38,6 +38,6 @@ public interface PluginConfigurationExpander * @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 expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java index ced5f4549621..28ad59624914 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportConfigurationExpander.java @@ -19,7 +19,7 @@ * under the License. */ -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; @@ -38,6 +38,6 @@ public interface ReportConfigurationExpander * @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 expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + void expandPluginConfiguration( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java index e0d645120900..e6d8898b13f9 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/plugin/ReportingConverter.java @@ -19,7 +19,7 @@ * under the License. */ -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; @@ -39,6 +39,6 @@ public interface ReportingConverter * @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 convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); + void convertReporting( Model model, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java index 1196acce9f3b..ec7eb25c763a 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileInjector.java @@ -35,7 +35,6 @@ import org.apache.maven.api.model.Plugin; import org.apache.maven.api.model.PluginContainer; import org.apache.maven.api.model.PluginExecution; -import org.apache.maven.api.model.Profile; import org.apache.maven.api.model.ReportPlugin; import org.apache.maven.api.model.ReportSet; import org.apache.maven.api.model.Reporting; @@ -58,24 +57,26 @@ public class DefaultProfileInjector private ProfileModelMerger merger = new ProfileModelMerger(); @Override - public Model injectProfile( Model model, Profile profile, ModelBuildingRequest request, - ModelProblemCollector problems ) + public void injectProfile( org.apache.maven.model.Model model, + org.apache.maven.model.Profile profile, + ModelBuildingRequest request, + ModelProblemCollector problems ) { if ( profile != null ) { - Model.Builder builder = Model.newBuilder( model ); - merger.mergeModelBase( builder, model, profile ); + Model.Builder builder = Model.newBuilder( model.getDelegate() ); + merger.mergeModelBase( builder, model.getDelegate(), profile.getDelegate() ); if ( profile.getBuild() != null ) { - Build build = model.getBuild() != null ? model.getBuild() : Build.newInstance(); + Build build = model.getBuild() != null ? model.getBuild().getDelegate() : Build.newInstance(); Build.Builder bbuilder = Build.newBuilder( build ); - merger.mergeBuildBase( bbuilder, build, profile.getBuild() ); + merger.mergeBuildBase( bbuilder, build, profile.getBuild().getDelegate() ); builder.build( bbuilder.build() ); } - return builder.build(); + + model.update( builder.build() ); } - return model; } /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java index 6989a401839c..75dc10f794a8 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/DefaultProfileSelector.java @@ -28,8 +28,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.api.model.Activation; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Activation; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java index 7103c43aea7f..fbd7ddf02285 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileInjector.java @@ -19,8 +19,8 @@ * under the License. */ -import org.apache.maven.api.model.Model; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Model; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblemCollector; @@ -41,6 +41,6 @@ public interface ProfileInjector * @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 injectProfile( Model model, Profile profile, ModelBuildingRequest request, ModelProblemCollector problems ); + void injectProfile( Model model, Profile profile, ModelBuildingRequest request, ModelProblemCollector problems ); } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java index f91aa1a43606..53ea8d9c04d0 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/ProfileSelector.java @@ -22,7 +22,7 @@ import java.util.Collection; import java.util.List; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; /** diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java index 25eda05a2eec..e45b8839a99f 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/FileProfileActivator.java @@ -25,9 +25,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.api.model.Activation; -import org.apache.maven.api.model.ActivationFile; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Activation; +import org.apache.maven.model.ActivationFile; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; import org.apache.maven.model.building.ModelProblemCollector; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java index 13566ecf6a5f..b21fd81f39e2 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/JdkVersionProfileActivator.java @@ -26,8 +26,8 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.api.model.Activation; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Activation; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java index 33f9700a3812..b3b21fa15c18 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/OperatingSystemProfileActivator.java @@ -22,9 +22,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.api.model.Activation; -import org.apache.maven.api.model.ActivationOS; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Activation; +import org.apache.maven.model.ActivationOS; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.profile.ProfileActivationContext; import org.codehaus.plexus.util.Os; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java index 84d78be5b0a1..1779147a6581 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/ProfileActivator.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.profile.ProfileActivationContext; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java index 53c67fba7681..1668443b0599 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/profile/activation/PropertyProfileActivator.java @@ -22,9 +22,9 @@ import javax.inject.Named; import javax.inject.Singleton; -import org.apache.maven.api.model.Activation; -import org.apache.maven.api.model.ActivationProperty; -import org.apache.maven.api.model.Profile; +import org.apache.maven.model.Activation; +import org.apache.maven.model.ActivationProperty; +import org.apache.maven.model.Profile; import org.apache.maven.model.building.ModelProblemCollector; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java index 21dd64ba8617..8264ed737a7f 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/WorkspaceModelResolver.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * WorkspaceModelResolver diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java index 81be8cefc58b..4a53081f37d2 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/validation/DefaultModelValidator.java @@ -44,7 +44,6 @@ import org.apache.maven.api.model.Exclusion; import org.apache.maven.api.model.InputLocation; import org.apache.maven.api.model.InputLocationTracker; -import org.apache.maven.api.model.Model; import org.apache.maven.api.model.Parent; import org.apache.maven.api.model.Plugin; import org.apache.maven.api.model.PluginExecution; @@ -54,6 +53,7 @@ import org.apache.maven.api.model.Reporting; import org.apache.maven.api.model.Repository; import org.apache.maven.api.model.Resource; +import org.apache.maven.model.Model; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.ModelProblem.Severity; import org.apache.maven.model.building.ModelProblem.Version; @@ -94,8 +94,11 @@ public DefaultModelValidator( ModelVersionProcessor versionProcessor ) } @Override - public void validateFileModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems ) + public void validateFileModel( Model ma, ModelBuildingRequest request, ModelProblemCollector problems ) { + + org.apache.maven.api.model.Model m = ma.getDelegate(); + Parent parent = m.getParent(); if ( parent != null ) { @@ -239,8 +242,10 @@ public void validateFileModel( Model m, ModelBuildingRequest request, ModelProbl } @Override - public void validateRawModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems ) + public void validateRawModel( Model ma, ModelBuildingRequest request, ModelProblemCollector problems ) { + org.apache.maven.api.model.Model m = ma.getDelegate(); + Parent parent = m.getParent(); if ( parent != null ) @@ -360,8 +365,10 @@ private void validate20RawPlugins( ModelProblemCollector problems, List } @Override - public void validateEffectiveModel( Model m, ModelBuildingRequest request, ModelProblemCollector problems ) + public void validateEffectiveModel( Model ma, ModelBuildingRequest request, ModelProblemCollector problems ) { + org.apache.maven.api.model.Model m = ma.getDelegate(); + validateStringNotEmpty( "modelVersion", problems, Severity.ERROR, Version.BASE, m.getModelVersion(), m ); validateCoordinateId( "groupId", problems, m.getGroupId(), m ); @@ -563,7 +570,8 @@ else if ( sysPath.contains( "${basedir}" ) || sysPath.contains( "${project.based } } - private void validate20RawDependenciesSelfReferencing( ModelProblemCollector problems, Model m, + private void validate20RawDependenciesSelfReferencing( ModelProblemCollector problems, + org.apache.maven.api.model.Model m, List dependencies, String prefix, ModelBuildingRequest request ) { @@ -589,7 +597,8 @@ private void validate20RawDependenciesSelfReferencing( ModelProblemCollector pro } } - private void validateEffectiveDependencies( ModelProblemCollector problems, Model m, List dependencies, + private void validateEffectiveDependencies( ModelProblemCollector problems, org.apache.maven.api.model.Model m, + List dependencies, boolean management, ModelBuildingRequest request ) { Severity errOn30 = getSeverity( request, ModelBuildingRequest.VALIDATION_LEVEL_MAVEN_3_0 ); @@ -629,7 +638,8 @@ private void validateEffectiveDependencies( ModelProblemCollector problems, Mode } } - private void validateEffectiveModelAgainstDependency( String prefix, ModelProblemCollector problems, Model m, + private void validateEffectiveModelAgainstDependency( String prefix, ModelProblemCollector problems, + org.apache.maven.api.model.Model m, Dependency d, ModelBuildingRequest request ) { String key = d.getGroupId() + ":" + d.getArtifactId() + ":" + d.getVersion() @@ -1357,13 +1367,11 @@ private static void addViolation( ModelProblemCollector problems, Severity sever buffer.append( ' ' ).append( message ); - // CHECKSTYLE_OFF: LineLength - problems.add( new ModelProblemCollectorRequest( severity, version ).setMessage( - buffer.toString() ).setLocation( getLocation( fieldName, tracker ) ) ); - // CHECKSTYLE_ON: LineLength + problems.add( new ModelProblemCollectorRequest( severity, version ) + .setMessage( buffer.toString() ).setLocation( getLocation( fieldName, tracker ) ) ); } - private static InputLocation getLocation( String fieldName, InputLocationTracker tracker ) + private static org.apache.maven.model.InputLocation getLocation( String fieldName, InputLocationTracker tracker ) { InputLocation location = null; @@ -1402,7 +1410,7 @@ private static InputLocation getLocation( String fieldName, InputLocationTracker } } - return location; + return location != null ? new org.apache.maven.model.InputLocation( location ) : null; } private static boolean equals( String s1, String s2 ) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java b/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java index f2144c2a66e1..198ba5ac5238 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/validation/ModelValidator.java @@ -19,7 +19,7 @@ * under the License. */ -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; diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java index b86e358adff5..cb112834a944 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderFactoryTest.java @@ -26,6 +26,7 @@ import org.apache.maven.api.xml.Dom; import org.apache.maven.api.model.Model; import org.apache.maven.model.v4.MavenXpp3Reader; +import org.codehaus.plexus.util.xml.Xpp3Dom; import org.junit.jupiter.api.Test; import static org.junit.jupiter.api.Assertions.assertTrue; @@ -60,7 +61,7 @@ public void testCompleteWiring() assertNotNull( result ); assertNotNull( result.getEffectiveModel() ); assertEquals( "activated", result.getEffectiveModel().getProperties().get( "profile.file" ) ); - Dom conf = result.getEffectiveModel().getBuild().getPlugins().get( 0 ).getConfiguration(); + Xpp3Dom conf = ( Xpp3Dom ) result.getEffectiveModel().getBuild().getPlugins().get( 0 ).getConfiguration(); assertNotNull( conf ); assertEquals( "1.5", conf.getChild( "source" ).getValue() ); assertEquals( " 1.5 ", conf.getChild( "target" ).getValue() ); diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java index defcaae25b3f..b6734e87daef 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/DefaultModelBuilderTest.java @@ -1,12 +1,6 @@ package org.apache.maven.model.building; - import static org.junit.jupiter.api.Assertions.assertNotNull; -import static org.junit.jupiter.api.Assertions.assertThrows; - -import java.io.File; - import java.util.concurrent.atomic.AtomicReference; - - /* +/* * 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 @@ -26,13 +20,18 @@ */ import org.apache.maven.api.model.Dependency; -import org.apache.maven.api.model.Model; import org.apache.maven.api.model.Parent; import org.apache.maven.api.model.Repository; +import org.apache.maven.model.Model; import org.apache.maven.model.resolution.InvalidRepositoryException; import org.apache.maven.model.resolution.ModelResolver; import org.apache.maven.model.resolution.UnresolvableModelException; import org.junit.jupiter.api.Test; +import java.io.File; +import java.util.concurrent.atomic.AtomicReference; + +import static org.junit.jupiter.api.Assertions.assertNotNull; +import static org.junit.jupiter.api.Assertions.assertThrows; /** * @author Guillaume Nodet @@ -99,7 +98,7 @@ public void testCycleInImports() static class CycleInImportsResolver extends BaseModelResolver { @Override - public ModelSource resolveModel(Dependency dependency, AtomicReference modified ) throws UnresolvableModelException + public ModelSource resolveModel( org.apache.maven.model.Dependency dependency ) throws UnresolvableModelException { switch ( dependency.getManagementKey() ) { diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java b/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java index 629cebd20fda..b311d771fd90 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/building/SimpleProblemCollector.java @@ -22,7 +22,7 @@ import java.util.ArrayList; import java.util.List; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; /** * A simple model problem collector for testing the model building components. diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java index 40fd611d6a19..6cd95e946a39 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/profile/activation/AbstractProfileActivatorTest.java @@ -59,7 +59,7 @@ protected void assertActivation( boolean active, Profile profile, ProfileActivat { SimpleProblemCollector problems = new SimpleProblemCollector(); - assertEquals( active, activator.isActive( profile, context, problems ) ); + assertEquals( active, activator.isActive( new org.apache.maven.model.Profile( profile ), context, problems ) ); assertEquals( 0, problems.getErrors().size(), problems.getErrors().toString() ); assertEquals( 0, problems.getWarnings().size(), problems.getWarnings().toString() ); diff --git a/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java b/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java index 7510d8b1169a..2c637004492f 100644 --- a/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java +++ b/maven-model-builder/src/test/java/org/apache/maven/model/validation/DefaultModelValidatorTest.java @@ -22,7 +22,7 @@ import java.io.InputStream; import java.util.List; -import org.apache.maven.api.model.Model; +import org.apache.maven.model.Model; import org.apache.maven.model.building.DefaultModelBuildingRequest; import org.apache.maven.model.building.ModelBuildingRequest; import org.apache.maven.model.building.SimpleProblemCollector; @@ -50,7 +50,7 @@ private Model read( String pom ) String resource = "/poms/validation/" + pom; InputStream is = getClass().getResourceAsStream( resource ); assertNotNull( is, "missing resource: " + resource ); - return new MavenXpp3Reader().read( is ); + return new Model( new MavenXpp3Reader().read( is ) ); } private SimpleProblemCollector validate( String pom ) diff --git a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java index b77232e8da87..3811365e40ed 100644 --- a/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java +++ b/maven-resolver-provider/src/main/java/org/apache/maven/repository/internal/DefaultArtifactDescriptorReader.java @@ -239,7 +239,7 @@ private Model loadPom( RepositorySystemSession session, ArtifactDescriptorReques pomArtifact.getVersion() ) ); } - model = new Model( modelBuilder.build( modelRequest ).getEffectiveModel() ); + model = modelBuilder.build( modelRequest ).getEffectiveModel(); } catch ( ModelBuildingException e ) { From 623d153675f0bf8c4707b2ef0ee7cac687e2b67c Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 11 Apr 2022 09:50:05 +0200 Subject: [PATCH 49/98] Fix model updates between object model / xpp3 config --- .../org/apache/maven/model/BaseObject.java | 28 +++++++++-------- maven-model/src/main/mdo/model-v3.vm | 9 ++++++ .../org/codehaus/plexus/util/xml/Xpp3Dom.java | 31 +++++++++++++++---- 3 files changed, 49 insertions(+), 19 deletions(-) diff --git a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java index d80058adc4a2..69536fd4a41e 100644 --- a/maven-model/src/main/java/org/apache/maven/model/BaseObject.java +++ b/maven-model/src/main/java/org/apache/maven/model/BaseObject.java @@ -24,7 +24,7 @@ public abstract class BaseObject implements Serializable, Cloneable, InputLocationTracker { - protected BaseObject parent; + protected ChildrenTracking childrenTracking; protected Object delegate; public BaseObject() @@ -34,31 +34,27 @@ public BaseObject() public BaseObject( Object delegate, BaseObject parent ) { this.delegate = delegate; - this.parent = parent; + this.childrenTracking = parent != null ? parent::replace : null; } - public Object getDelegate() - { - return delegate; - } - - public BaseObject getParent() + public BaseObject( Object delegate, ChildrenTracking parent ) { - return parent; + this.delegate = delegate; + this.childrenTracking = parent; } - public void setParent( BaseObject parent ) + public Object getDelegate() { - this.parent = parent; + return delegate; } public void update( Object newDelegate ) { if ( delegate != newDelegate ) { - if ( parent != null ) + if ( childrenTracking != null ) { - parent.replace( delegate, newDelegate ); + childrenTracking.replace( delegate, newDelegate ); } delegate = newDelegate; } @@ -68,4 +64,10 @@ protected boolean replace( Object oldDelegate, Object newDelegate ) { return false; } + + @FunctionalInterface + protected interface ChildrenTracking + { + boolean replace( Object oldDelegate, Object newDelegate ); + } } diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 9c718c23ed2e..c5b818d7b886 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -195,6 +195,7 @@ public class ${class.name} if ( ! Objects.equals( ( ( Xpp3Dom ) ${field.name} ).getDom(), getDelegate().${pfx}${cap}() ) ) { update( getDelegate().with${cap}( ( ( Xpp3Dom ) ${field.name} ).getDom() ) ); + ( ( Xpp3Dom ) ${field.name} ).setChildrenTracking( this::replace ); } #else if ( !Objects.equals( ${field.name}, getDelegate().${pfx}${cap}() ) ) @@ -202,8 +203,10 @@ public class ${class.name} #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 @@ -224,6 +227,7 @@ public class ${class.name} update( getDelegate().with${cap}( Stream.concat( getDelegate().get${cap}().stream(), Stream.of( ${v}.getDelegate() ) ) .collect( Collectors.toList() ) ) ); + ${v}.childrenTracking = this::replace; #end } @@ -264,6 +268,11 @@ public class ${class.name} 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.Dom ) newDelegate ) ); + } #end #end return false; diff --git a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java index 0330c17b6f5f..5718e07fcd9b 100644 --- a/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java +++ b/maven-xml-impl/src/main/java/org/codehaus/plexus/util/xml/Xpp3Dom.java @@ -69,7 +69,7 @@ public class Xpp3Dom */ public static final String DEFAULT_SELF_COMBINATION_MODE = SELF_COMBINATION_MERGE; - private Xpp3Dom parent; + private ChildrenTracking childrenTracking; private Dom dom; public Xpp3Dom( String name ) @@ -114,7 +114,13 @@ public Xpp3Dom( Dom dom ) public Xpp3Dom( Dom dom, Xpp3Dom parent ) { this.dom = dom; - this.parent = parent; + this.childrenTracking = parent::replace; + } + + public Xpp3Dom( Dom dom, ChildrenTracking childrenTracking ) + { + this.dom = dom; + this.childrenTracking = childrenTracking; } public Dom getDom() @@ -223,6 +229,7 @@ public void addChild( Xpp3Dom xpp3Dom ) { List children = new ArrayList<>( dom.getChildren() ); children.add( xpp3Dom.dom ); + xpp3Dom.childrenTracking = this::replace; update( new org.apache.maven.internal.xml.Xpp3Dom( dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); } @@ -452,18 +459,30 @@ public static boolean isEmpty( String str ) private void update( Dom dom ) { - if ( parent != null ) + if ( childrenTracking != null ) { - parent.replace( this.dom, dom ); + childrenTracking.replace( this.dom, dom ); } this.dom = dom; } - private void replace( Dom prevChild, Dom newChild ) + private boolean replace( Object prevChild, Object newChild ) { List children = new ArrayList<>( dom.getChildren() ); - children.replaceAll( d -> d == prevChild ? newChild : d ); + children.replaceAll( d -> d == prevChild ? ( Dom ) newChild : d ); update( new org.apache.maven.internal.xml.Xpp3Dom( dom.getName(), dom.getValue(), dom.getAttributes(), children, dom.getInputLocation() ) ); + return true; + } + + public void setChildrenTracking( ChildrenTracking childrenTracking ) + { + this.childrenTracking = childrenTracking; + } + + @FunctionalInterface + public interface ChildrenTracking + { + boolean replace( Object oldDelegate, Object newDelegate ); } } From 157617d0a64a5e52bd0c14b608216bbdabcb07b6 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 11 Apr 2022 10:00:18 +0200 Subject: [PATCH 50/98] Fix model updates between object model / xpp3 config --- maven-model/src/main/mdo/model-v3.vm | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index c5b818d7b886..420686918ce6 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -183,7 +183,7 @@ public class ${class.name} #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}() ) : null; + return getDelegate().${pfx}${cap}() != null ? new Xpp3Dom( getDelegate().${pfx}${cap}(), this::replace ) : null; #else return getDelegate().${pfx}${cap}(); #end From e7822c21b1ac5b0fd927731ed77428495537e3b8 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 11 Apr 2022 11:11:06 +0200 Subject: [PATCH 51/98] Fix xml plexus config toString --- .../internal/xml/XmlPlexusConfiguration.java | 43 ++++++++++++++++--- 1 file changed, 38 insertions(+), 5 deletions(-) diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java index ba496a04a88d..d215105b01e9 100644 --- a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/XmlPlexusConfiguration.java @@ -23,13 +23,46 @@ import org.codehaus.plexus.configuration.DefaultPlexusConfiguration; import org.codehaus.plexus.configuration.PlexusConfiguration; -public class XmlPlexusConfiguration +public class XmlPlexusConfiguration extends DefaultPlexusConfiguration { public static PlexusConfiguration toPlexusConfiguration( Dom node ) { - DefaultPlexusConfiguration dfc = new DefaultPlexusConfiguration( node.getName(), node.getValue() ); - node.getAttributes().forEach( dfc::setAttribute ); - node.getChildren().forEach( c -> dfc.addChild( toPlexusConfiguration( c ) ) ); - return dfc; + return new XmlPlexusConfiguration( node ); } + + public XmlPlexusConfiguration( Dom node ) + { + super( node.getName(), node.getValue() ); + node.getAttributes().forEach( this::setAttribute ); + node.getChildren().forEach( c -> this.addChild( new XmlPlexusConfiguration( c ) ) ); + } + + @Override + public String toString() + { + final StringBuilder buf = new StringBuilder().append( '<' ).append( getName() ); + for ( final String a : getAttributeNames() ) + { + buf.append( ' ' ).append( a ).append( "=\"" ).append( getAttribute( a ) ).append( '"' ); + } + if ( getChildCount() > 0 ) + { + buf.append( '>' ); + for ( int i = 0, size = getChildCount(); i < size; i++ ) + { + buf.append( getChild( i ) ); + } + buf.append( "' ); + } + else if ( null != getValue() ) + { + buf.append( '>' ).append( getValue() ).append( "' ); + } + else + { + buf.append( "/>" ); + } + return buf.append( '\n' ).toString(); + } + } From 7533b381747eebd5536f979c3feacca0e28357a1 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 13 Apr 2022 10:36:23 +0200 Subject: [PATCH 52/98] Remove the package cycle between org.apache.maven.api and org.apache.maven.api.services --- .../maven/api/{services => }/Service.java | 2 +- .../java/org/apache/maven/api/Session.java | 204 +++-------- .../maven/api/services/ArtifactDeployer.java | 1 + .../maven/api/services/ArtifactFactory.java | 1 + .../maven/api/services/ArtifactInstaller.java | 1 + .../maven/api/services/ArtifactManager.java | 1 + .../maven/api/services/ArtifactResolver.java | 1 + .../api/services/DependencyCollector.java | 1 + .../maven/api/services/DependencyFactory.java | 1 + .../api/services/DependencyResolver.java | 1 + .../api/services/LocalRepositoryManager.java | 1 + .../maven/api/services/ProjectBuilder.java | 1 + .../maven/api/services/ProjectManager.java | 1 + .../maven/api/services/RepositoryFactory.java | 1 + .../maven/api/services/ToolchainManager.java | 1 + .../maven/api/services/xml/XmlFactory.java | 2 +- .../maven/internal/impl/DefaultSession.java | 325 ++++++++++++++++-- .../apache/maven/internal/impl/TestApi.java | 4 +- 18 files changed, 364 insertions(+), 186 deletions(-) rename api/maven-api-core/src/main/java/org/apache/maven/api/{services => }/Service.java (95%) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Service.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java similarity index 95% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/Service.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/Service.java index fcf8d87fcddc..ed9d2b301388 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Service.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java @@ -1,4 +1,4 @@ -package org.apache.maven.api.services; +package org.apache.maven.api; /* * Licensed to the Apache Software Foundation (ASF) under one diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index 2aa678aacf38..f5e6bad7efd9 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -23,7 +23,6 @@ import org.apache.maven.api.annotations.ThreadSafe; import java.nio.file.Path; -import java.util.Arrays; import java.util.Collection; import java.util.List; import java.util.NoSuchElementException; @@ -31,25 +30,6 @@ import java.util.Properties; import java.util.function.Predicate; -import org.apache.maven.api.services.ArtifactDeployer; -import org.apache.maven.api.services.ArtifactDeployerException; -import org.apache.maven.api.services.ArtifactFactory; -import org.apache.maven.api.services.ArtifactInstaller; -import org.apache.maven.api.services.ArtifactInstallerException; -import org.apache.maven.api.services.ArtifactManager; -import org.apache.maven.api.services.ArtifactResolver; -import org.apache.maven.api.services.ArtifactResolverException; -import org.apache.maven.api.services.ArtifactResolverResult; -import org.apache.maven.api.services.DependencyCollector; -import org.apache.maven.api.services.DependencyCollectorException; -import org.apache.maven.api.services.DependencyCollectorResult; -import org.apache.maven.api.services.DependencyFactory; -import org.apache.maven.api.services.DependencyResolver; -import org.apache.maven.api.services.DependencyResolverException; -import org.apache.maven.api.services.DependencyResolverResult; -import org.apache.maven.api.services.LocalRepositoryManager; -import org.apache.maven.api.services.RepositoryFactory; -import org.apache.maven.api.services.Service; import org.apache.maven.api.model.Repository; import org.apache.maven.api.settings.Settings; @@ -132,219 +112,137 @@ public interface Session /** * Shortcut for getService(RepositoryFactory.class).createLocal(...) - * @see RepositoryFactory#createLocal(Path) + * @see org.apache.maven.api.services.RepositoryFactory#createLocal(Path) */ - default LocalRepository createLocalRepository( Path path ) - { - return getService( RepositoryFactory.class ).createLocal( path ); - } + LocalRepository createLocalRepository( Path path ); /** * Shortcut for getService(RepositoryFactory.class).createRemote(...) - * @see RepositoryFactory#createRemote(String, String) + * @see org.apache.maven.api.services.RepositoryFactory#createRemote(String, String) */ @Nonnull - default RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ) - { - return getService( RepositoryFactory.class ) - .createRemote( id, url ); - } + RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ); /** * Shortcut for getService(RepositoryFactory.class).createRemote(...) - * @see RepositoryFactory#createRemote(Repository) + * @see org.apache.maven.api.services.RepositoryFactory#createRemote(Repository) */ @Nonnull - default RemoteRepository createRemoteRepository( @Nonnull Repository repository ) - { - return getService( RepositoryFactory.class ) - .createRemote( repository ); - } + RemoteRepository createRemoteRepository( @Nonnull Repository repository ); /** * Shortcut for getService(ArtifactFactory.class).create(...) - * @see ArtifactFactory#create(Session, String, String, String, String) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String) */ - default Artifact createArtifact( String groupId, String artifactId, String version, String extension ) - { - return getService( ArtifactFactory.class ) - .create( this, groupId, artifactId, version, extension ); - } + Artifact createArtifact( String groupId, String artifactId, String version, String extension ); /** * Shortcut for getService(ArtifactFactory.class).create(...) - * @see ArtifactFactory#create(Session, String, String, String, String, String, String) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String, String, String) */ - default Artifact createArtifact( String groupId, String artifactId, String version, String classifier, - String extension, String type ) - { - return getService( ArtifactFactory.class ) - .create( this, groupId, artifactId, version, classifier, extension, type ); - } + Artifact createArtifact( String groupId, String artifactId, String version, String classifier, + String extension, String type ); /** * Shortcut for getService(ArtifactResolver.class).resolve(...) - * @see ArtifactResolver#resolve(Session, Artifact) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Artifact) * - * @throws ArtifactResolverException if the artifact resolution failed + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed */ - default ArtifactResolverResult resolveArtifact( Artifact artifact ) - { - return getService( ArtifactResolver.class ) - .resolve( this, artifact ); - } + Artifact resolveArtifact( Artifact artifact ); /** * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} - * @see ArtifactInstaller#install(Session, Collection) + * @see org.apache.maven.api.services.ArtifactInstaller#install(Session, Collection) * - * @throws ArtifactInstallerException if the artifacts installation failed + * @throws org.apache.maven.api.services.ArtifactInstallerException if the artifacts installation failed */ - default void installArtifacts( Artifact... artifacts ) - { - installArtifacts( Arrays.asList( artifacts ) ); - } + void installArtifacts( Artifact... artifacts ); /** * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} - * @see ArtifactInstaller#install(Session, Collection) + * @see org.apache.maven.api.services.ArtifactInstaller#install(Session, Collection) * - * @throws ArtifactInstallerException if the artifacts installation failed + * @throws org.apache.maven.api.services.ArtifactInstallerException if the artifacts installation failed */ - default void installArtifacts( Collection artifacts ) - { - getService( ArtifactInstaller.class ) - .install( this, artifacts ); - } + void installArtifacts( Collection artifacts ); /** * Shortcut for getService(ArtifactDeployer.class).deploy(...) - * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection) + * @see org.apache.maven.api.services.ArtifactDeployer#deploy(Session, RemoteRepository, Collection) * - * @throws ArtifactDeployerException if the artifacts deployment failed + * @throws org.apache.maven.api.services.ArtifactDeployerException if the artifacts deployment failed */ - default void deployArtifact( RemoteRepository repository, Artifact... artifacts ) - { - getService( ArtifactDeployer.class ) - .deploy( this, repository, Arrays.asList( artifacts ) ); - } + void deployArtifact( RemoteRepository repository, Artifact... artifacts ); /** * Shortcut for getService(ArtifactManager.class).setPath(...) - * @see ArtifactManager#setPath(Artifact, Path) + * @see org.apache.maven.api.services.ArtifactManager#setPath(Artifact, Path) */ - default void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ) - { - getService( ArtifactManager.class ) - .setPath( artifact, path ); - } + void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ); /** * Shortcut for getService(ArtifactManager.class).getPath(...) - * @see ArtifactManager#getPath(Artifact) + * @see org.apache.maven.api.services.ArtifactManager#getPath(Artifact) */ @Nonnull - default Optional getArtifactPath( @Nonnull Artifact artifact ) - { - return getService( ArtifactManager.class ) - .getPath( artifact ); - } + Optional getArtifactPath( @Nonnull Artifact artifact ); /** * Shortcut for getService(ArtifactManager.class).isSnapshot(...) - * @see ArtifactManager#isSnapshot(String) + * @see org.apache.maven.api.services.ArtifactManager#isSnapshot(String) */ - default boolean isVersionSnapshot( @Nonnull String version ) - { - return getService( ArtifactManager.class ) - .isSnapshot( version ); - } + boolean isVersionSnapshot( @Nonnull String version ); /** * Shortcut for getService(DependencyFactory.class).create(...) - * @see DependencyFactory#create(Session, Artifact) + * @see org.apache.maven.api.services.DependencyFactory#create(Session, Artifact) */ @Nonnull - default Dependency createDependency( @Nonnull Artifact artifact ) - { - return getService( DependencyFactory.class ) - .create( this, artifact ); - } + Dependency createDependency( @Nonnull Artifact artifact ); /** * Shortcut for getService(DependencyCollector.class).collect(...) - * @see DependencyCollector#collect(Session, Artifact) + * @see org.apache.maven.api.services.DependencyCollector#collect(Session, Artifact) * - * @throws DependencyCollectorException if the dependency collection failed + * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed */ @Nonnull - default DependencyCollectorResult collectDependencies( @Nonnull Artifact artifact ) - { - return getService( DependencyCollector.class ) - .collect( this, artifact ); - } + Node collectDependencies( @Nonnull Artifact artifact ); /** * Shortcut for getService(DependencyCollector.class).collect(...) - * @see DependencyCollector#collect(Session, Project) + * @see org.apache.maven.api.services.DependencyCollector#collect(Session, Project) * - * @throws DependencyCollectorException if the dependency collection failed + * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed */ @Nonnull - default DependencyCollectorResult collectDependencies( @Nonnull Project project ) - { - return getService( DependencyCollector.class ) - .collect( this, project ); - } + Node collectDependencies( @Nonnull Project project ); /** * Shortcut for getService(DependencyCollector.class).collect(...) - * @see DependencyCollector#collect(Session, Dependency) + * @see org.apache.maven.api.services.DependencyCollector#collect(Session, Dependency) * - * @throws DependencyCollectorException if the dependency collection failed + * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed */ @Nonnull - default DependencyCollectorResult collectDependencies( @Nonnull Dependency dependency ) - { - return getService( DependencyCollector.class ) - .collect( this, dependency ); - } + Node collectDependencies( @Nonnull Dependency dependency ); /** * Shortcut for getService(DependencyResolver.class).resolve(...) - * @see DependencyResolver#resolve(Session, Dependency, Predicate) + * @see org.apache.maven.api.services.DependencyResolver#resolve(Session, Dependency, Predicate) * - * @throws DependencyResolverException if the dependency resolution failed + * @throws org.apache.maven.api.services.DependencyResolverException if the dependency resolution failed */ @Nonnull - default DependencyResolverResult resolveDependencies( @Nonnull Dependency dependency ) - { - return getService( DependencyResolver.class ) - .resolve( this, dependency, null ); - } - - default Path getPathForLocalArtifact( @Nonnull Artifact artifact ) - { - return getService( LocalRepositoryManager.class ) - .getPathForLocalArtifact( this, getLocalRepository(), artifact ); - } - - default Path getPathForLocalMetadata( Metadata metadata ) - { - return getService( LocalRepositoryManager.class ) - .getPathForLocalMetadata( this, getLocalRepository(), metadata ); - } - - default Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ) - { - return getService( LocalRepositoryManager.class ) - .getPathForRemoteArtifact( this, getLocalRepository(), remote, artifact ); - } - - default Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ) - { - return getService( LocalRepositoryManager.class ) - .getPathForRemoteMetadata( this, getLocalRepository(), remote, metadata ); - } + Node resolveDependencies( @Nonnull Dependency dependency ); + + Path getPathForLocalArtifact( @Nonnull Artifact artifact ); + + Path getPathForLocalMetadata( Metadata metadata ); + + Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ); + + Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java index 1156c028235d..9074451939ec 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java @@ -21,6 +21,7 @@ import java.util.Collection; +import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.RemoteRepository; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java index 8a46f42a5e0d..ceaf0e957b21 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.annotations.Nonnull; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java index 0cafa236369d..ecaab2c05e4e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java @@ -22,6 +22,7 @@ import java.util.Collection; import java.util.Collections; +import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java index e5d90a832020..e33d3edc9867 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java index 272a0375b0d4..1d63362cd44e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java index e802eff211fb..fe08b1fabc59 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.Session; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java index ffcdb24a275f..4d479df6929c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java index de8d02186812..11e80be3c5a6 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java @@ -21,6 +21,7 @@ import java.util.function.Predicate; +import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Dependency; import org.apache.maven.api.Node; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java index fc9d3b1fbbad..abd7a282090e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java @@ -25,6 +25,7 @@ import org.apache.maven.api.LocalRepository; import org.apache.maven.api.Metadata; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Service; import org.apache.maven.api.Session; public interface LocalRepositoryManager extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java index bf857576e45c..fb5c3c375bd1 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java index cee11892a720..4c94e649c816 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java index eaea90b7eab8..d641fbae19e3 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java @@ -23,6 +23,7 @@ import org.apache.maven.api.LocalRepository; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Repository; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java index 7c5da04d97fb..8f83fb3dbd78 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java @@ -22,6 +22,7 @@ import java.util.List; import java.util.Map; +import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Toolchain; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java index a466533e97d3..a3b09151ed34 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java @@ -25,7 +25,7 @@ import java.io.Writer; import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.services.Service; +import org.apache.maven.api.Service; public interface XmlFactory extends Service { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index dea547948724..37b7ace3dd56 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -19,56 +19,64 @@ * under the License. */ -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.Nullable; - import java.io.File; import java.nio.file.Path; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; +import java.util.Optional; import java.util.Properties; import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; import org.apache.maven.RepositoryUtils; +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; import org.apache.maven.api.Listener; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; import org.apache.maven.api.SessionData; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactDeployerException; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactInstallerException; import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactResolverException; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyCollectorException; +import org.apache.maven.api.services.DependencyFactory; +import org.apache.maven.api.services.DependencyResolver; +import org.apache.maven.api.services.DependencyResolverException; import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectManager; import org.apache.maven.api.services.RepositoryFactory; -import org.apache.maven.api.services.Service; -import org.apache.maven.api.Session; -import org.apache.maven.api.Artifact; -import org.apache.maven.api.Metadata; -import org.apache.maven.api.Dependency; -import org.apache.maven.api.Node; -import org.apache.maven.api.Project; -import org.apache.maven.api.LocalRepository; -import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.services.ToolchainManager; import org.apache.maven.api.services.xml.ModelXmlFactory; import org.apache.maven.api.services.xml.SettingsXmlFactory; import org.apache.maven.api.services.xml.ToolchainsXmlFactory; +import org.apache.maven.api.settings.Settings; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.MavenSession; import org.apache.maven.project.MavenProject; -import org.apache.maven.api.services.ArtifactResolver; -import org.apache.maven.api.services.ArtifactDeployer; -import org.apache.maven.api.services.ArtifactFactory; -import org.apache.maven.api.services.ArtifactInstaller; -import org.apache.maven.api.services.DependencyCollector; -import org.apache.maven.api.services.DependencyFactory; -import org.apache.maven.api.services.DependencyResolver; -import org.apache.maven.api.services.ProjectBuilder; -import org.apache.maven.api.settings.Settings; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; @@ -114,7 +122,7 @@ public DefaultSession( @Nonnull MavenSession session, this.repositories = repositories != null ? repositories : mavenSession.getRequest().getRemoteRepositories().stream() - .map( RepositoryUtils::toRepo ).map( this::getRemoteRepository ).collect( Collectors.toList() ); + .map( RepositoryUtils::toRepo ).map( this::getRemoteRepository ).collect( Collectors.toList() ); this.projectBuilder = projectBuilder; this.mavenRepositorySystem = mavenRepositorySystem; this.toolchainManagerPrivate = toolchainManagerPrivate; @@ -172,17 +180,20 @@ public void set( @Nonnull Object key, @Nullable Object value ) { data.set( key, value ); } + @Override public boolean set( @Nonnull Object key, @Nullable Object oldValue, @Nullable Object newValue ) { return data.set( key, oldValue, newValue ); } + @Nullable @Override public Object get( @Nonnull Object key ) { return data.get( key ); } + @Nullable @Override public Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier supplier ) @@ -191,7 +202,7 @@ public Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier su Object value = data.get( key ); if ( value == null ) { - if ( ! data.set( key, null, supplier.get() ) ) + if ( !data.set( key, null, supplier.get() ) ) { value = data.get( key ); } @@ -208,7 +219,7 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) nonNull( localRepository, "localRepository" ); if ( session.getLocalRepository() != null && Objects.equals( session.getLocalRepository().getBasedir().toPath(), - localRepository.getPath() ) ) + localRepository.getPath() ) ) { return this; } @@ -219,9 +230,9 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) RepositorySystemSession repoSession = new DefaultRepositorySystemSession( session ) .setLocalRepositoryManager( localRepositoryManager ); MavenSession newSession = new MavenSession( mavenSession.getContainer(), repoSession, - mavenSession.getRequest(), mavenSession.getResult() ); + mavenSession.getRequest(), mavenSession.getResult() ); return new DefaultSession( newSession, repositorySystem, - repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); } @Nonnull @@ -229,7 +240,7 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) public Session withRemoteRepositories( @Nonnull List repositories ) { return new DefaultSession( mavenSession, repositorySystem, - repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); } @Nonnull @@ -374,7 +385,7 @@ public org.eclipse.aether.repository.LocalRepository toRepository( LocalReposito { if ( repository instanceof DefaultLocalRepository ) { - return ( ( DefaultLocalRepository ) repository ).getRepository(); + return ( (DefaultLocalRepository) repository ).getRepository(); } else { @@ -433,7 +444,7 @@ public org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ) { if ( dependency instanceof DefaultDependency ) { - return ( ( DefaultDependency ) dependency ).getDependency(); + return ( (DefaultDependency) dependency ).getDependency(); } else { @@ -528,4 +539,260 @@ public Collection getListeners() return Collections.unmodifiableCollection( listeners ); } + // + // Shortcut implementations + // + + /** + * Shortcut for getService(RepositoryFactory.class).createLocal(...) + * + * @see RepositoryFactory#createLocal(Path) + */ + @Override + public LocalRepository createLocalRepository( Path path ) + { + return getService( RepositoryFactory.class ).createLocal( path ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * + * @see RepositoryFactory#createRemote(String, String) + */ + @Nonnull + @Override + public RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ) + { + return getService( RepositoryFactory.class ) + .createRemote( id, url ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * + * @see RepositoryFactory#createRemote(Repository) + */ + @Nonnull + @Override + public RemoteRepository createRemoteRepository( @Nonnull Repository repository ) + { + return getService( RepositoryFactory.class ) + .createRemote( repository ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String) + */ + @Override + public Artifact createArtifact( String groupId, String artifactId, String version, String extension ) + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, extension ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + @Override + public Artifact createArtifact( String groupId, String artifactId, String version, String classifier, + String extension, String type ) + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, classifier, extension, type ); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Artifact) + */ + @Override + public Artifact resolveArtifact( Artifact artifact ) + { + return getService( ArtifactResolver.class ) + .resolve( this, artifact ) + .getArtifact(); + } + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * + * @throws ArtifactInstallerException if the artifacts installation failed + * @see ArtifactInstaller#install(Session, Collection) + */ + @Override + public void installArtifacts( Artifact... artifacts ) + { + installArtifacts( Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * + * @throws ArtifactInstallerException if the artifacts installation failed + * @see ArtifactInstaller#install(Session, Collection) + */ + @Override + public void installArtifacts( Collection artifacts ) + { + getService( ArtifactInstaller.class ) + .install( this, artifacts ); + } + + /** + * Shortcut for getService(ArtifactDeployer.class).deploy(...) + * + * @throws ArtifactDeployerException if the artifacts deployment failed + * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection) + */ + @Override + public void deployArtifact( RemoteRepository repository, Artifact... artifacts ) + { + getService( ArtifactDeployer.class ) + .deploy( this, repository, Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for getService(ArtifactManager.class).setPath(...) + * + * @see ArtifactManager#setPath(Artifact, Path) + */ + @Override + public void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ) + { + getService( ArtifactManager.class ) + .setPath( artifact, path ); + } + + /** + * Shortcut for getService(ArtifactManager.class).getPath(...) + * + * @see ArtifactManager#getPath(Artifact) + */ + @Nonnull + @Override + public Optional getArtifactPath( @Nonnull Artifact artifact ) + { + return getService( ArtifactManager.class ) + .getPath( artifact ); + } + + /** + * Shortcut for getService(ArtifactManager.class).isSnapshot(...) + * + * @see ArtifactManager#isSnapshot(String) + */ + @Override + public boolean isVersionSnapshot( @Nonnull String version ) + { + return getService( ArtifactManager.class ) + .isSnapshot( version ); + } + + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * + * @see DependencyFactory#create(Session, Artifact) + */ + @Nonnull + @Override + public Dependency createDependency( @Nonnull Artifact artifact ) + { + return getService( DependencyFactory.class ) + .create( this, artifact ); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Artifact) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Artifact artifact ) + { + return getService( DependencyCollector.class ) + .collect( this, artifact ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Project) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Project project ) + { + return getService( DependencyCollector.class ) + .collect( this, project ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Dependency) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Dependency dependency ) + { + return getService( DependencyCollector.class ) + .collect( this, dependency ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyResolver.class).resolve(...) + * + * @throws DependencyResolverException if the dependency resolution failed + * @see DependencyResolver#resolve(Session, Dependency, Predicate) + */ + @Nonnull + @Override + public Node resolveDependencies( @Nonnull Dependency dependency ) + { + return getService( DependencyResolver.class ) + .resolve( this, dependency, null ) + .getRoot(); + } + + @Override + public Path getPathForLocalArtifact( @Nonnull Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalArtifact( this, getLocalRepository(), artifact ); + } + + @Override + public Path getPathForLocalMetadata( Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalMetadata( this, getLocalRepository(), metadata ); + } + + @Override + public Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteArtifact( this, getLocalRepository(), remote, artifact ); + } + + @Override + public Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteMetadata( this, getLocalRepository(), remote, metadata ); + } + } diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index d33adc1c1491..957f40473009 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -93,7 +93,7 @@ void testCreateAndResolveArtifact() throws Exception Artifact artifact = session.createArtifact( "org.codehaus.plexus", "plexus-utils", "1.4.5", "pom" ); assertFalse( artifact.getPath().isPresent() ); - Artifact resolved = session.resolveArtifact( artifact ).getArtifact(); + Artifact resolved = session.resolveArtifact( artifact ); assertNotSame( resolved, artifact ); assertTrue( resolved.getPath().isPresent() ); assertNotNull( resolved.getPath().get() ); @@ -105,7 +105,7 @@ void testCreateAndResolveArtifact() throws Exception assertNotNull( project ); artifact = session.createArtifact( "org.codehaus.plexus", "plexus-container-default", "1.0-alpha-32", "jar" ); - Node root = session.collectDependencies( artifact ).getRoot(); + Node root = session.collectDependencies( artifact ); assertNotNull( root ); } From 00e853334651ace9ed425c395a9e4af48eda5be4 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 13 Apr 2022 11:18:22 +0200 Subject: [PATCH 53/98] Add some javadoc to Service interface --- .../src/main/java/org/apache/maven/api/Service.java | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java index ed9d2b301388..98623e04bb44 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java @@ -21,6 +21,14 @@ import org.apache.maven.api.annotations.ThreadSafe; +/** + * Marker interface for all services provided by the {@link Session}. + * + * Services can be retrieved from the session using the + * {@link Session#getService(Class)} method. + * + * @see Session#getService(Class) + */ @ThreadSafe public interface Service { From fbeab2e07e636c958a657b1de293a8c7e3a9c60d Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 13 Apr 2022 11:26:58 +0200 Subject: [PATCH 54/98] Fix mojo javadoc and bring back the instantiationStrategy --- .../src/main/java/org/apache/maven/api/plugin/Mojo.java | 4 +--- .../java/org/apache/maven/api/plugin/annotations/Mojo.java | 6 ++++++ 2 files changed, 7 insertions(+), 3 deletions(-) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java index 593c29cf9997..fe94753b27c0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java @@ -25,9 +25,7 @@ * This interface forms the contract required for Mojos to interact with the Maven * infrastructure.
* It features an execute() method, which triggers the Mojo's build-process behavior, and can throw - * a MojoExecutionException or MojoFailureException if error conditions occur.
- * Also included is the setLog(...) method, which simply allows Maven to inject a logging mechanism which - * will allow the Mojo to communicate to the outside world through standard Maven channels. + * a MojoException if error conditions occur.
*/ @FunctionalInterface @Consumer public interface Mojo diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java index 87eb8665e4f3..79169a0b062d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java @@ -62,6 +62,12 @@ */ ResolutionScope requiresDependencyCollection() default ResolutionScope.NONE; + /** + * your Mojo instantiation strategy. (Only per-lookup and singleton are supported) + * @return the instantiation strategy + */ + InstantiationStrategy instantiationStrategy() default InstantiationStrategy.PER_LOOKUP; + /** * does your mojo requires a project to be executed? * @return requires a project From 9f3321ad79b1745daadd533adb44eb6da60c60e2 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 14 Apr 2022 16:05:46 +0200 Subject: [PATCH 55/98] Split session to allow easier reuse for stubs --- .../maven/internal/impl/AbstractSession.java | 498 ++++++++++++++++++ .../maven/internal/impl/DefaultArtifact.java | 4 +- .../internal/impl/DefaultDependency.java | 5 +- .../maven/internal/impl/DefaultNode.java | 4 +- .../maven/internal/impl/DefaultProject.java | 6 +- .../internal/impl/DefaultProjectManager.java | 2 +- .../maven/internal/impl/DefaultSession.java | 451 +--------------- 7 files changed, 512 insertions(+), 458 deletions(-) create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java new file mode 100644 index 000000000000..2c5fe109589b --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java @@ -0,0 +1,498 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.io.File; +import java.nio.file.Path; +import java.util.Arrays; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; +import java.util.Optional; +import java.util.WeakHashMap; +import java.util.concurrent.CopyOnWriteArrayList; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Listener; +import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Metadata; +import org.apache.maven.api.Node; +import org.apache.maven.api.Project; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Repository; +import org.apache.maven.api.services.ArtifactDeployer; +import org.apache.maven.api.services.ArtifactDeployerException; +import org.apache.maven.api.services.ArtifactFactory; +import org.apache.maven.api.services.ArtifactInstaller; +import org.apache.maven.api.services.ArtifactInstallerException; +import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.ArtifactResolverException; +import org.apache.maven.api.services.DependencyCollector; +import org.apache.maven.api.services.DependencyCollectorException; +import org.apache.maven.api.services.DependencyFactory; +import org.apache.maven.api.services.DependencyResolver; +import org.apache.maven.api.services.DependencyResolverException; +import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.artifact.repository.ArtifactRepository; +import org.apache.maven.project.MavenProject; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public abstract class AbstractSession implements Session +{ + + private final List listeners = new CopyOnWriteArrayList<>(); + private final Map allNodes + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allArtifacts + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allRepositories + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allProjects + = Collections.synchronizedMap( new WeakHashMap<>() ); + private final Map allDependencies + = Collections.synchronizedMap( new WeakHashMap<>() ); + + public RemoteRepository getRemoteRepository( org.eclipse.aether.repository.RemoteRepository repository ) + { + return allRepositories.computeIfAbsent( repository, DefaultRemoteRepository::new ); + } + + public Node getNode( org.eclipse.aether.graph.DependencyNode node ) + { + return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n ) ); + } + + @Nonnull + public Artifact getArtifact( @Nonnull org.eclipse.aether.artifact.Artifact artifact ) + { + return allArtifacts.computeIfAbsent( artifact, a -> new DefaultArtifact( this, a ) ); + } + + @Nonnull + public Dependency getDependency( @Nonnull org.eclipse.aether.graph.Dependency dependency ) + { + return allDependencies.computeIfAbsent( dependency, d -> new DefaultDependency( this, d ) ); + } + + public List getProjects( List projects ) + { + return projects == null ? null : projects.stream() + .map( this::getProject ) + .collect( Collectors.toList() ); + } + + public Project getProject( MavenProject project ) + { + return allProjects.computeIfAbsent( project.getId(), id -> new DefaultProject( this, project ) ); + } + + public List toRepositories( List repositories ) + { + return repositories == null ? null : repositories.stream() + .map( this::toRepository ) + .collect( Collectors.toList() ); + } + + public org.eclipse.aether.repository.RemoteRepository toRepository( RemoteRepository repository ) + { + if ( repository instanceof DefaultRemoteRepository ) + { + return ( (DefaultRemoteRepository) repository ).getRepository(); + } + else + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + } + + public org.eclipse.aether.repository.LocalRepository toRepository( LocalRepository repository ) + { + if ( repository instanceof DefaultLocalRepository ) + { + return ( (DefaultLocalRepository) repository ).getRepository(); + } + else + { + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + } + + public List toArtifactRepositories( List repositories ) + { + return repositories == null ? null : repositories.stream() + .map( this::toArtifactRepository ) + .collect( Collectors.toList() ); + } + + public abstract ArtifactRepository toArtifactRepository( RemoteRepository repository ); + + public List toDependencies( Collection dependencies ) + { + return dependencies == null ? null : dependencies.stream() + .map( this::toDependency ) + .collect( Collectors.toList() ); + } + + public abstract org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ); + + public List toArtifacts( Collection artifacts ) + { + return artifacts == null ? null : artifacts.stream() + .map( this::toArtifact ) + .collect( Collectors.toList() ); + } + + public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact ) + { + File file = getService( ArtifactManager.class ).getPath( artifact ).map( Path::toFile ).orElse( null ); + if ( artifact instanceof DefaultArtifact ) + { + org.eclipse.aether.artifact.Artifact a = ( (DefaultArtifact) artifact ).getArtifact(); + if ( Objects.equals( file, a.getFile() ) ) + { + return a; + } + } + return new org.eclipse.aether.artifact.DefaultArtifact( + artifact.getGroupId(), + artifact.getArtifactId(), + artifact.getClassifier(), + artifact.getExtension(), + artifact.getVersion(), + null, + file + ); + } + + public org.eclipse.aether.metadata.Metadata toMetadata( Metadata metadata ) + { + /* + if ( metadata instanceof ProjectArtifactMetadata ) + { + Artifact pomArtifact = new SubArtifact( mainArtifact, "", "pom" ); + pomArtifact = pomArtifact.setFile( ( (ProjectArtifactMetadata) metadata ).getFile() ); + request.addArtifact( pomArtifact ); + } + else if ( // metadata instanceof SnapshotArtifactRepositoryMetadata || + metadata instanceof ArtifactRepositoryMetadata ) + { + // eaten, handled by repo system + } + else if ( metadata instanceof org.apache.maven.shared.transfer.metadata.ArtifactMetadata ) + { + org.apache.maven.shared.transfer.metadata.ArtifactMetadata transferMetadata = + (org.apache.maven.shared.transfer.metadata.ArtifactMetadata) metadata; + + request.addMetadata( new Maven31MetadataBridge( metadata ).setFile( transferMetadata.getFile() ) ); + } + + */ + // TODO + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + @Override + public void registerListener( @Nonnull Listener listener ) + { + listeners.add( nonNull( listener ) ); + } + + @Override + public void unregisterListener( @Nonnull Listener listener ) + { + listeners.remove( nonNull( listener ) ); + } + + @Nonnull + @Override + public Collection getListeners() + { + return Collections.unmodifiableCollection( listeners ); + } + + // + // Shortcut implementations + // + + /** + * Shortcut for getService(RepositoryFactory.class).createLocal(...) + * + * @see RepositoryFactory#createLocal(Path) + */ + @Override + public LocalRepository createLocalRepository( Path path ) + { + return getService( RepositoryFactory.class ).createLocal( path ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * + * @see RepositoryFactory#createRemote(String, String) + */ + @Nonnull + @Override + public RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ) + { + return getService( RepositoryFactory.class ) + .createRemote( id, url ); + } + + /** + * Shortcut for getService(RepositoryFactory.class).createRemote(...) + * + * @see RepositoryFactory#createRemote(Repository) + */ + @Nonnull + @Override + public RemoteRepository createRemoteRepository( @Nonnull Repository repository ) + { + return getService( RepositoryFactory.class ) + .createRemote( repository ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String) + */ + @Override + public Artifact createArtifact( String groupId, String artifactId, String version, String extension ) + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, extension ); + } + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + @Override + public Artifact createArtifact( String groupId, String artifactId, String version, String classifier, + String extension, String type ) + { + return getService( ArtifactFactory.class ) + .create( this, groupId, artifactId, version, classifier, extension, type ); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Artifact) + */ + @Override + public Artifact resolveArtifact( Artifact artifact ) + { + return getService( ArtifactResolver.class ) + .resolve( this, artifact ) + .getArtifact(); + } + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * + * @throws ArtifactInstallerException if the artifacts installation failed + * @see ArtifactInstaller#install(Session, Collection) + */ + @Override + public void installArtifacts( Artifact... artifacts ) + { + installArtifacts( Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} + * + * @throws ArtifactInstallerException if the artifacts installation failed + * @see ArtifactInstaller#install(Session, Collection) + */ + @Override + public void installArtifacts( Collection artifacts ) + { + getService( ArtifactInstaller.class ) + .install( this, artifacts ); + } + + /** + * Shortcut for getService(ArtifactDeployer.class).deploy(...) + * + * @throws ArtifactDeployerException if the artifacts deployment failed + * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection) + */ + @Override + public void deployArtifact( RemoteRepository repository, Artifact... artifacts ) + { + getService( ArtifactDeployer.class ) + .deploy( this, repository, Arrays.asList( artifacts ) ); + } + + /** + * Shortcut for getService(ArtifactManager.class).setPath(...) + * + * @see ArtifactManager#setPath(Artifact, Path) + */ + @Override + public void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ) + { + getService( ArtifactManager.class ) + .setPath( artifact, path ); + } + + /** + * Shortcut for getService(ArtifactManager.class).getPath(...) + * + * @see ArtifactManager#getPath(Artifact) + */ + @Nonnull + @Override + public Optional getArtifactPath( @Nonnull Artifact artifact ) + { + return getService( ArtifactManager.class ) + .getPath( artifact ); + } + + /** + * Shortcut for getService(ArtifactManager.class).isSnapshot(...) + * + * @see ArtifactManager#isSnapshot(String) + */ + @Override + public boolean isVersionSnapshot( @Nonnull String version ) + { + return getService( ArtifactManager.class ) + .isSnapshot( version ); + } + + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * + * @see DependencyFactory#create(Session, Artifact) + */ + @Nonnull + @Override + public Dependency createDependency( @Nonnull Artifact artifact ) + { + return getService( DependencyFactory.class ) + .create( this, artifact ); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Artifact) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Artifact artifact ) + { + return getService( DependencyCollector.class ) + .collect( this, artifact ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Project) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Project project ) + { + return getService( DependencyCollector.class ) + .collect( this, project ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyCollector.class).collect(...) + * + * @throws DependencyCollectorException if the dependency collection failed + * @see DependencyCollector#collect(Session, Dependency) + */ + @Nonnull + @Override + public Node collectDependencies( @Nonnull Dependency dependency ) + { + return getService( DependencyCollector.class ) + .collect( this, dependency ) + .getRoot(); + } + + /** + * Shortcut for getService(DependencyResolver.class).resolve(...) + * + * @throws DependencyResolverException if the dependency resolution failed + * @see DependencyResolver#resolve(Session, Dependency, Predicate) + */ + @Nonnull + @Override + public Node resolveDependencies( @Nonnull Dependency dependency ) + { + return getService( DependencyResolver.class ) + .resolve( this, dependency, null ) + .getRoot(); + } + + @Override + public Path getPathForLocalArtifact( @Nonnull Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalArtifact( this, getLocalRepository(), artifact ); + } + + @Override + public Path getPathForLocalMetadata( Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForLocalMetadata( this, getLocalRepository(), metadata ); + } + + @Override + public Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteArtifact( this, getLocalRepository(), remote, artifact ); + } + + @Override + public Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ) + { + return getService( LocalRepositoryManager.class ) + .getPathForRemoteMetadata( this, getLocalRepository(), remote, metadata ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java index 7d18c94be39a..4116758eb67b 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -35,10 +35,10 @@ */ public class DefaultArtifact implements Artifact { - private final @Nonnull DefaultSession session; + private final @Nonnull AbstractSession session; private final @Nonnull org.eclipse.aether.artifact.Artifact artifact; - public DefaultArtifact( @Nonnull DefaultSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact ) + public DefaultArtifact( @Nonnull AbstractSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact ) { this.session = nonNull( session, "session can not be null" ); this.artifact = nonNull( artifact, "artifact can not be null" ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java index d308088caf1d..2291ae6a7d8e 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java @@ -32,10 +32,11 @@ public class DefaultDependency implements Dependency { - private final DefaultSession session; + private final AbstractSession session; private final org.eclipse.aether.graph.Dependency dependency; - public DefaultDependency( @Nonnull DefaultSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency ) + public DefaultDependency( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.graph.Dependency dependency ) { this.session = nonNull( session, "session" ); this.dependency = nonNull( dependency, "dependency" ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java index a11611f1e9d7..04c3d5527803 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java @@ -34,10 +34,10 @@ public class DefaultNode implements Node { - private final @Nonnull DefaultSession session; + private final @Nonnull AbstractSession session; private final @Nonnull org.eclipse.aether.graph.DependencyNode node; - public DefaultNode( @Nonnull DefaultSession session, + public DefaultNode( @Nonnull AbstractSession session, @Nonnull org.eclipse.aether.graph.DependencyNode node ) { this.session = session; diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java index 17fa50990276..bd53ee239ea4 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -42,16 +42,16 @@ public class DefaultProject implements Project { - private final DefaultSession session; + private final AbstractSession session; private final MavenProject project; - public DefaultProject( DefaultSession session, MavenProject project ) + public DefaultProject( AbstractSession session, MavenProject project ) { this.session = session; this.project = project; } - public DefaultSession getSession() + public AbstractSession getSession() { return session; } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java index 7af8591ffd18..ad2dcec7a47c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java @@ -58,7 +58,7 @@ public Optional getPath( Project project ) @Override public Collection getAttachedArtifacts( Project project ) { - DefaultSession session = ( (DefaultProject ) project ).getSession(); + AbstractSession session = ( (DefaultProject ) project ).getSession(); Collection attached = ( ( DefaultProject ) project ).getProject().getAttachedArtifacts().stream() .map( RepositoryUtils::toArtifact ) .map( session::getArtifact ) diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index 37b7ace3dd56..c9f0961af92b 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -19,51 +19,31 @@ * under the License. */ -import java.io.File; -import java.nio.file.Path; -import java.util.Arrays; -import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; -import java.util.Optional; import java.util.Properties; -import java.util.WeakHashMap; -import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Predicate; import java.util.function.Supplier; import java.util.stream.Collectors; import org.apache.maven.RepositoryUtils; -import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; -import org.apache.maven.api.Listener; import org.apache.maven.api.LocalRepository; -import org.apache.maven.api.Metadata; -import org.apache.maven.api.Node; -import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.SessionData; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; -import org.apache.maven.api.model.Repository; import org.apache.maven.api.services.ArtifactDeployer; -import org.apache.maven.api.services.ArtifactDeployerException; import org.apache.maven.api.services.ArtifactFactory; import org.apache.maven.api.services.ArtifactInstaller; -import org.apache.maven.api.services.ArtifactInstallerException; import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactResolver; -import org.apache.maven.api.services.ArtifactResolverException; import org.apache.maven.api.services.DependencyCollector; -import org.apache.maven.api.services.DependencyCollectorException; import org.apache.maven.api.services.DependencyFactory; import org.apache.maven.api.services.DependencyResolver; -import org.apache.maven.api.services.DependencyResolverException; import org.apache.maven.api.services.LocalRepositoryManager; import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectManager; @@ -76,7 +56,6 @@ import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.MavenSession; -import org.apache.maven.project.MavenProject; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; @@ -84,7 +63,7 @@ import static org.apache.maven.internal.impl.Utils.nonNull; -public class DefaultSession implements Session +public class DefaultSession extends AbstractSession { private final MavenSession mavenSession; @@ -94,21 +73,9 @@ public class DefaultSession implements Session private final org.apache.maven.project.ProjectBuilder projectBuilder; private final MavenRepositorySystem mavenRepositorySystem; private final DefaultToolchainManagerPrivate toolchainManagerPrivate; - private final List listeners = new CopyOnWriteArrayList<>(); private final ArtifactManager artifactManager = new DefaultArtifactManager(); private final ProjectManager projectManager = new DefaultProjectManager( artifactManager ); - private final Map allNodes - = Collections.synchronizedMap( new WeakHashMap<>() ); - private final Map allArtifacts - = Collections.synchronizedMap( new WeakHashMap<>() ); - private final Map allRepositories - = Collections.synchronizedMap( new WeakHashMap<>() ); - private final Map allProjects - = Collections.synchronizedMap( new WeakHashMap<>() ); - private final Map allDependencies - = Collections.synchronizedMap( new WeakHashMap<>() ); - public DefaultSession( @Nonnull MavenSession session, @Nonnull RepositorySystem repositorySystem, @Nullable List repositories, @@ -130,7 +97,7 @@ public DefaultSession( @Nonnull MavenSession session, MavenSession getMavenSession() { - return null; + return mavenSession; } @Nonnull @@ -327,81 +294,7 @@ public RepositorySystem getRepositorySystem() return repositorySystem; } - public RemoteRepository getRemoteRepository( org.eclipse.aether.repository.RemoteRepository repository ) - { - return allRepositories.computeIfAbsent( repository, DefaultRemoteRepository::new ); - } - - public Node getNode( org.eclipse.aether.graph.DependencyNode node ) - { - return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n ) ); - } - - @Nonnull - public Artifact getArtifact( @Nonnull org.eclipse.aether.artifact.Artifact artifact ) - { - return allArtifacts.computeIfAbsent( artifact, a -> new DefaultArtifact( this, a ) ); - } - - @Nonnull - public Dependency getDependency( @Nonnull org.eclipse.aether.graph.Dependency dependency ) - { - return allDependencies.computeIfAbsent( dependency, d -> new DefaultDependency( this, d ) ); - } - - public List getProjects( List projects ) - { - return projects == null ? null : projects.stream() - .map( this::getProject ) - .collect( Collectors.toList() ); - } - - public Project getProject( MavenProject project ) - { - return allProjects.computeIfAbsent( project.getId(), id -> new DefaultProject( this, project ) ); - } - - public List toRepositories( List repositories ) - { - return repositories == null ? null : repositories.stream() - .map( this::toRepository ) - .collect( Collectors.toList() ); - } - - public org.eclipse.aether.repository.RemoteRepository toRepository( RemoteRepository repository ) - { - if ( repository instanceof DefaultRemoteRepository ) - { - return ( (DefaultRemoteRepository) repository ).getRepository(); - } - else - { - // TODO - throw new UnsupportedOperationException( "Not implemented yet" ); - } - } - - public org.eclipse.aether.repository.LocalRepository toRepository( LocalRepository repository ) - { - if ( repository instanceof DefaultLocalRepository ) - { - return ( (DefaultLocalRepository) repository ).getRepository(); - } - else - { - // TODO - throw new UnsupportedOperationException( "Not implemented yet" ); - } - } - - public List toArtifactRepositories( List repositories ) - { - return repositories == null ? null : repositories.stream() - .map( this::toArtifactRepository ) - .collect( Collectors.toList() ); - } - - private ArtifactRepository toArtifactRepository( RemoteRepository repository ) + public ArtifactRepository toArtifactRepository( RemoteRepository repository ) { if ( repository instanceof DefaultRemoteRepository ) { @@ -433,13 +326,6 @@ private ArtifactRepository toArtifactRepository( RemoteRepository repository ) } } - public List toDependencies( Collection dependencies ) - { - return dependencies == null ? null : dependencies.stream() - .map( this::toDependency ) - .collect( Collectors.toList() ); - } - public org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ) { if ( dependency instanceof DefaultDependency ) @@ -464,335 +350,4 @@ public org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ) } } - public List toArtifacts( Collection artifacts ) - { - return artifacts == null ? null : artifacts.stream() - .map( this::toArtifact ) - .collect( Collectors.toList() ); - } - - public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact ) - { - File file = getService( ArtifactManager.class ).getPath( artifact ).map( Path::toFile ).orElse( null ); - if ( artifact instanceof DefaultArtifact ) - { - org.eclipse.aether.artifact.Artifact a = ( (DefaultArtifact) artifact ).getArtifact(); - if ( Objects.equals( file, a.getFile() ) ) - { - return a; - } - } - return new org.eclipse.aether.artifact.DefaultArtifact( - artifact.getGroupId(), - artifact.getArtifactId(), - artifact.getClassifier(), - artifact.getExtension(), - artifact.getVersion(), - null, - file - ); - } - - public org.eclipse.aether.metadata.Metadata toMetadata( Metadata metadata ) - { - /* - if ( metadata instanceof ProjectArtifactMetadata ) - { - Artifact pomArtifact = new SubArtifact( mainArtifact, "", "pom" ); - pomArtifact = pomArtifact.setFile( ( (ProjectArtifactMetadata) metadata ).getFile() ); - request.addArtifact( pomArtifact ); - } - else if ( // metadata instanceof SnapshotArtifactRepositoryMetadata || - metadata instanceof ArtifactRepositoryMetadata ) - { - // eaten, handled by repo system - } - else if ( metadata instanceof org.apache.maven.shared.transfer.metadata.ArtifactMetadata ) - { - org.apache.maven.shared.transfer.metadata.ArtifactMetadata transferMetadata = - (org.apache.maven.shared.transfer.metadata.ArtifactMetadata) metadata; - - request.addMetadata( new Maven31MetadataBridge( metadata ).setFile( transferMetadata.getFile() ) ); - } - - */ - // TODO - throw new UnsupportedOperationException( "Not implemented yet" ); - } - - @Override - public void registerListener( @Nonnull Listener listener ) - { - listeners.add( nonNull( listener ) ); - } - - @Override - public void unregisterListener( @Nonnull Listener listener ) - { - listeners.remove( nonNull( listener ) ); - } - - @Nonnull - @Override - public Collection getListeners() - { - return Collections.unmodifiableCollection( listeners ); - } - - // - // Shortcut implementations - // - - /** - * Shortcut for getService(RepositoryFactory.class).createLocal(...) - * - * @see RepositoryFactory#createLocal(Path) - */ - @Override - public LocalRepository createLocalRepository( Path path ) - { - return getService( RepositoryFactory.class ).createLocal( path ); - } - - /** - * Shortcut for getService(RepositoryFactory.class).createRemote(...) - * - * @see RepositoryFactory#createRemote(String, String) - */ - @Nonnull - @Override - public RemoteRepository createRemoteRepository( @Nonnull String id, @Nonnull String url ) - { - return getService( RepositoryFactory.class ) - .createRemote( id, url ); - } - - /** - * Shortcut for getService(RepositoryFactory.class).createRemote(...) - * - * @see RepositoryFactory#createRemote(Repository) - */ - @Nonnull - @Override - public RemoteRepository createRemoteRepository( @Nonnull Repository repository ) - { - return getService( RepositoryFactory.class ) - .createRemote( repository ); - } - - /** - * Shortcut for getService(ArtifactFactory.class).create(...) - * - * @see ArtifactFactory#create(Session, String, String, String, String) - */ - @Override - public Artifact createArtifact( String groupId, String artifactId, String version, String extension ) - { - return getService( ArtifactFactory.class ) - .create( this, groupId, artifactId, version, extension ); - } - - /** - * Shortcut for getService(ArtifactFactory.class).create(...) - * - * @see ArtifactFactory#create(Session, String, String, String, String, String, String) - */ - @Override - public Artifact createArtifact( String groupId, String artifactId, String version, String classifier, - String extension, String type ) - { - return getService( ArtifactFactory.class ) - .create( this, groupId, artifactId, version, classifier, extension, type ); - } - - /** - * Shortcut for getService(ArtifactResolver.class).resolve(...) - * - * @throws ArtifactResolverException if the artifact resolution failed - * @see ArtifactResolver#resolve(Session, Artifact) - */ - @Override - public Artifact resolveArtifact( Artifact artifact ) - { - return getService( ArtifactResolver.class ) - .resolve( this, artifact ) - .getArtifact(); - } - - /** - * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} - * - * @throws ArtifactInstallerException if the artifacts installation failed - * @see ArtifactInstaller#install(Session, Collection) - */ - @Override - public void installArtifacts( Artifact... artifacts ) - { - installArtifacts( Arrays.asList( artifacts ) ); - } - - /** - * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} - * - * @throws ArtifactInstallerException if the artifacts installation failed - * @see ArtifactInstaller#install(Session, Collection) - */ - @Override - public void installArtifacts( Collection artifacts ) - { - getService( ArtifactInstaller.class ) - .install( this, artifacts ); - } - - /** - * Shortcut for getService(ArtifactDeployer.class).deploy(...) - * - * @throws ArtifactDeployerException if the artifacts deployment failed - * @see ArtifactDeployer#deploy(Session, RemoteRepository, Collection) - */ - @Override - public void deployArtifact( RemoteRepository repository, Artifact... artifacts ) - { - getService( ArtifactDeployer.class ) - .deploy( this, repository, Arrays.asList( artifacts ) ); - } - - /** - * Shortcut for getService(ArtifactManager.class).setPath(...) - * - * @see ArtifactManager#setPath(Artifact, Path) - */ - @Override - public void setArtifactPath( @Nonnull Artifact artifact, @Nonnull Path path ) - { - getService( ArtifactManager.class ) - .setPath( artifact, path ); - } - - /** - * Shortcut for getService(ArtifactManager.class).getPath(...) - * - * @see ArtifactManager#getPath(Artifact) - */ - @Nonnull - @Override - public Optional getArtifactPath( @Nonnull Artifact artifact ) - { - return getService( ArtifactManager.class ) - .getPath( artifact ); - } - - /** - * Shortcut for getService(ArtifactManager.class).isSnapshot(...) - * - * @see ArtifactManager#isSnapshot(String) - */ - @Override - public boolean isVersionSnapshot( @Nonnull String version ) - { - return getService( ArtifactManager.class ) - .isSnapshot( version ); - } - - /** - * Shortcut for getService(DependencyFactory.class).create(...) - * - * @see DependencyFactory#create(Session, Artifact) - */ - @Nonnull - @Override - public Dependency createDependency( @Nonnull Artifact artifact ) - { - return getService( DependencyFactory.class ) - .create( this, artifact ); - } - - /** - * Shortcut for getService(DependencyCollector.class).collect(...) - * - * @throws DependencyCollectorException if the dependency collection failed - * @see DependencyCollector#collect(Session, Artifact) - */ - @Nonnull - @Override - public Node collectDependencies( @Nonnull Artifact artifact ) - { - return getService( DependencyCollector.class ) - .collect( this, artifact ) - .getRoot(); - } - - /** - * Shortcut for getService(DependencyCollector.class).collect(...) - * - * @throws DependencyCollectorException if the dependency collection failed - * @see DependencyCollector#collect(Session, Project) - */ - @Nonnull - @Override - public Node collectDependencies( @Nonnull Project project ) - { - return getService( DependencyCollector.class ) - .collect( this, project ) - .getRoot(); - } - - /** - * Shortcut for getService(DependencyCollector.class).collect(...) - * - * @throws DependencyCollectorException if the dependency collection failed - * @see DependencyCollector#collect(Session, Dependency) - */ - @Nonnull - @Override - public Node collectDependencies( @Nonnull Dependency dependency ) - { - return getService( DependencyCollector.class ) - .collect( this, dependency ) - .getRoot(); - } - - /** - * Shortcut for getService(DependencyResolver.class).resolve(...) - * - * @throws DependencyResolverException if the dependency resolution failed - * @see DependencyResolver#resolve(Session, Dependency, Predicate) - */ - @Nonnull - @Override - public Node resolveDependencies( @Nonnull Dependency dependency ) - { - return getService( DependencyResolver.class ) - .resolve( this, dependency, null ) - .getRoot(); - } - - @Override - public Path getPathForLocalArtifact( @Nonnull Artifact artifact ) - { - return getService( LocalRepositoryManager.class ) - .getPathForLocalArtifact( this, getLocalRepository(), artifact ); - } - - @Override - public Path getPathForLocalMetadata( Metadata metadata ) - { - return getService( LocalRepositoryManager.class ) - .getPathForLocalMetadata( this, getLocalRepository(), metadata ); - } - - @Override - public Path getPathForRemoteArtifact( RemoteRepository remote, Artifact artifact ) - { - return getService( LocalRepositoryManager.class ) - .getPathForRemoteArtifact( this, getLocalRepository(), remote, artifact ); - } - - @Override - public Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ) - { - return getService( LocalRepositoryManager.class ) - .getPathForRemoteMetadata( this, getLocalRepository(), remote, metadata ); - } - } From 131e96beffd8650ef219c0cfde7b48f484932846 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 14 Apr 2022 16:06:16 +0200 Subject: [PATCH 56/98] Add back boolean setters --- api/maven-api-model/src/main/mdo/maven.mdo | 83 ++++++++++++++++++- .../profiles/ProfilesConversionUtils.java | 2 +- .../LegacyRepositorySystemTest.java | 2 +- .../maven/bridge/MavenRepositorySystem.java | 2 +- .../AbstractCoreMavenComponentTestCase.java | 2 +- 5 files changed, 84 insertions(+), 7 deletions(-) diff --git a/api/maven-api-model/src/main/mdo/maven.mdo b/api/maven-api-model/src/main/mdo/maven.mdo index c4fa4802c727..7bd835d0987b 100644 --- a/api/maven-api-model/src/main/mdo/maven.mdo +++ b/api/maven-api-model/src/main/mdo/maven.mdo @@ -1154,6 +1154,25 @@ return ( getOptional() != null ) ? Boolean.parseBoolean( getOptional() ) : false; } + ]]> + + + + 4.0.0/4.1.0 + + + + + + 4.0.0+ + + + + + + 4.0.0/4.1.0 + + + + + + 4.0.0+ + + 4.0.0+ + + + + 4.0.0/4.1.0 + + @@ -2205,8 +2252,26 @@ { return ( getExtensions() != null ) ? Boolean.parseBoolean( getExtensions() ) : false; } - + ]]> + + + + 4.0.0/4.1.0 + + + + + + 4.0.0+ + + executionMap = null; + /** * Reset the {@code executionMap} field to {@code null} */ @@ -2449,6 +2514,18 @@ return ( getExcludeDefaults() != null ) ? Boolean.parseBoolean( getExcludeDefaults() ) : false; } + ]]> + + + + 4.0.0/4.1.0 + + diff --git a/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java b/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java index 17f8592ec8bd..154176eecf76 100644 --- a/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java +++ b/maven-compat/src/main/java/org/apache/maven/profiles/ProfilesConversionUtils.java @@ -145,7 +145,7 @@ private static Repository convertFromProfileXmlRepository( org.apache.maven.prof private static org.apache.maven.model.RepositoryPolicy convertRepositoryPolicy( RepositoryPolicy profileXmlRepo ) { org.apache.maven.model.RepositoryPolicy policy = new org.apache.maven.model.RepositoryPolicy(); - policy.setEnabled( Boolean.toString( profileXmlRepo.isEnabled() ) ); + policy.setEnabled( profileXmlRepo.isEnabled() ); policy.setUpdatePolicy( profileXmlRepo.getUpdatePolicy() ); policy.setChecksumPolicy( profileXmlRepo.getChecksumPolicy() ); return policy; diff --git a/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java b/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java index 78353beb827f..f68a9961fb80 100644 --- a/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java +++ b/maven-compat/src/test/java/org/apache/maven/repository/LegacyRepositorySystemTest.java @@ -67,7 +67,7 @@ protected List getRemoteRepositories() File repoDir = new File( getBasedir(), "src/test/remote-repo" ).getAbsoluteFile(); RepositoryPolicy policy = new RepositoryPolicy(); - policy.setEnabled( Boolean.toString( true ) ); + policy.setEnabled( true ); policy.setChecksumPolicy( "ignore" ); policy.setUpdatePolicy( "always" ); diff --git a/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java b/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java index 0f7689f629ab..79563822d05c 100644 --- a/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java +++ b/maven-core/src/main/java/org/apache/maven/bridge/MavenRepositorySystem.java @@ -350,7 +350,7 @@ public static org.apache.maven.model.RepositoryPolicy fromSettingsRepositoryPoli org.apache.maven.model.RepositoryPolicy modelRepositoryPolicy = new org.apache.maven.model.RepositoryPolicy(); if ( settingsRepositoryPolicy != null ) { - modelRepositoryPolicy.setEnabled( Boolean.toString( settingsRepositoryPolicy.isEnabled() ) ); + modelRepositoryPolicy.setEnabled( settingsRepositoryPolicy.isEnabled() ); modelRepositoryPolicy.setUpdatePolicy( settingsRepositoryPolicy.getUpdatePolicy() ); modelRepositoryPolicy.setChecksumPolicy( settingsRepositoryPolicy.getChecksumPolicy() ); } diff --git a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java index a2256ec088d3..bb3574ae41d8 100644 --- a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java +++ b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java @@ -195,7 +195,7 @@ protected List getRemoteRepositories() File repoDir = new File( getBasedir(), "src/test/remote-repo" ).getAbsoluteFile(); RepositoryPolicy policy = new RepositoryPolicy(); - policy.setEnabled( Boolean.toString( true ) ); + policy.setEnabled( true ); policy.setChecksumPolicy( "ignore" ); policy.setUpdatePolicy( "always" ); From abd74de5eef47d40ee4d15c52ab92e5e2042f979 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 14 Apr 2022 16:07:50 +0200 Subject: [PATCH 57/98] Restore compatibility on the ModelWriter --- .../maven/model/io/DefaultModelWriter.java | 19 ++++++++++ .../apache/maven/model/io/ModelWriter.java | 36 +++++++++++++++++++ 2 files changed, 55 insertions(+) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java index 9cebee4b98d8..31435693317c 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/DefaultModelWriter.java @@ -90,4 +90,23 @@ public void write( OutputStream output, Map options, Model model } } + @Override + public void write( File output, Map options, org.apache.maven.model.Model model ) throws IOException + { + write( output, options, model.getDelegate() ); + } + + @Override + public void write( Writer output, Map options, org.apache.maven.model.Model model ) + throws IOException + { + write( output, options, model.getDelegate() ); + } + + @Override + public void write( OutputStream output, Map options, org.apache.maven.model.Model model ) + throws IOException + { + write( output, options, model.getDelegate() ); + } } diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java index 0e1f41b3be9a..d32c1c2cea45 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/io/ModelWriter.java @@ -71,4 +71,40 @@ void write( Writer output, Map options, Model model ) void write( OutputStream output, Map options, Model model ) throws IOException; + /** + * Writes the supplied model to the specified file. Any non-existing parent directories of the output file will be + * created automatically. + * + * @param output The file to serialize the model to, must not be {@code null}. + * @param options The options to use for serialization, may be {@code null} to use the default values. + * @param model The model to serialize, must not be {@code null}. + * @throws IOException If the model could not be serialized. + */ + void write( File output, Map options, org.apache.maven.model.Model model ) + throws IOException; + + /** + * Writes the supplied model to the specified character writer. The writer will be automatically closed before the + * method returns. + * + * @param output The writer to serialize the model to, must not be {@code null}. + * @param options The options to use for serialization, may be {@code null} to use the default values. + * @param model The model to serialize, must not be {@code null}. + * @throws IOException If the model could not be serialized. + */ + void write( Writer output, Map options, org.apache.maven.model.Model model ) + throws IOException; + + /** + * Writes the supplied model to the specified byte stream. The stream will be automatically closed before the method + * returns. + * + * @param output The stream to serialize the model to, must not be {@code null}. + * @param options The options to use for serialization, may be {@code null} to use the default values. + * @param model The model to serialize, must not be {@code null}. + * @throws IOException If the model could not be serialized. + */ + void write( OutputStream output, Map options, org.apache.maven.model.Model model ) + throws IOException; + } From 9926d3de4c7bf05df28e9d532173547993e3639c Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 14 Apr 2022 16:08:04 +0200 Subject: [PATCH 58/98] Add back removeXxx on model lists --- maven-model/src/main/mdo/model-v3.vm | 16 ++++++++++++++++ 1 file changed, 16 insertions(+) diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 420686918ce6..4d293a3ec594 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -231,6 +231,22 @@ public class ${class.name} #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 ) From 61eb2ee5e15570a49beb3689376023a33cb93a18 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 27 Apr 2022 11:09:46 +0200 Subject: [PATCH 59/98] Simplifications --- ...DefaultRepositorySystemSessionFactory.java | 25 ++++--------------- 1 file changed, 5 insertions(+), 20 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java index 492c09b3f82c..1d5af8736d19 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/aether/DefaultRepositorySystemSessionFactory.java @@ -136,18 +136,9 @@ public DefaultRepositorySystemSession newRepositorySession( MavenExecutionReques session.setOffline( request.isOffline() ); session.setChecksumPolicy( request.getGlobalChecksumPolicy() ); - if ( request.isNoSnapshotUpdates() ) - { - session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_NEVER ); - } - else if ( request.isUpdateSnapshots() ) - { - session.setUpdatePolicy( RepositoryPolicy.UPDATE_POLICY_ALWAYS ); - } - else - { - session.setUpdatePolicy( null ); - } + session.setUpdatePolicy( request.isNoSnapshotUpdates() + ? RepositoryPolicy.UPDATE_POLICY_NEVER + : request.isUpdateSnapshots() ? RepositoryPolicy.UPDATE_POLICY_ALWAYS : null ); int errorPolicy = 0; errorPolicy |= request.isCacheNotFound() ? ResolutionErrorPolicy.CACHE_NOT_FOUND @@ -180,14 +171,8 @@ else if ( request.isUpdateSnapshots() ) session.setLocalRepositoryManager( repoSystem.newLocalRepositoryManager( session, localRepo ) ); } - if ( request.getWorkspaceReader() != null ) - { - session.setWorkspaceReader( request.getWorkspaceReader() ); - } - else - { - session.setWorkspaceReader( workspaceRepository ); - } + session.setWorkspaceReader( + request.getWorkspaceReader() != null ? request.getWorkspaceReader() : workspaceRepository ); DefaultSettingsDecryptionRequest decrypt = new DefaultSettingsDecryptionRequest(); decrypt.setProxies( Proxy.proxyToApiV4( request.getProxies() ) ); From 90f04c6fa25e50ef424320cb2766feba95c0771b Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 21 Jun 2022 12:43:57 +0200 Subject: [PATCH 60/98] Fix plexus xml duplication --- plexus-utils/pom.xml | 106 +++++++++++++++++++++++++++++++++++++++++++ pom.xml | 4 +- 2 files changed, 109 insertions(+), 1 deletion(-) create mode 100644 plexus-utils/pom.xml diff --git a/plexus-utils/pom.xml b/plexus-utils/pom.xml new file mode 100644 index 000000000000..dd201e11642b --- /dev/null +++ b/plexus-utils/pom.xml @@ -0,0 +1,106 @@ + + + + + + + maven + org.apache.maven + 4.0.0-alpha-1-SNAPSHOT + + 4.0.0 + + org.codehaus.plexus + plexus-utils + 4.0.0-alpha-1-SNAPSHOT + + + + + org.apache.maven.plugins + maven-dependency-plugin + 3.1.1 + + + unpack + compile + + unpack + + + + + org.codehaus.plexus + plexus-utils + 3.4.2 + jar + false + ${project.build.directory}/classes + **/*.class,**/*.xml + + org/codehaus/plexus/util/xml/Xpp3Dom.class, + org/codehaus/plexus/util/xml/Xpp3DomBuilder.class + + + + **/*.java + false + true + + + + + + org.codehaus.mojo + animal-sniffer-maven-plugin + + + check-java-compat + none + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/pom.xml b/pom.xml index b9e0bbe26402..1e6d588d0e5b 100644 --- a/pom.xml +++ b/pom.xml @@ -54,7 +54,7 @@ under the License. 3.2.0 2.1.0 1.26 - 3.4.2 + 4.0.0-alpha-1-SNAPSHOT 4.2.3 30.1-jre 1.0.1 @@ -84,6 +84,7 @@ under the License. maven-model-transform api maven-xml-impl + plexus-utils maven-core maven-settings maven-settings-builder @@ -570,6 +571,7 @@ under the License. src/main/appended-resources/licenses/MIT-slf4j-api-1.7.30.txt src/main/appended-resources/licenses/EPL-1.0.txt src/main/appended-resources/licenses/unrecognized-javax.annotation-api-1.3.2.txt + plexus-utils/target/** From a1604df8698532f1824f792497daf84ccbc5c4f4 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 21 Jun 2022 16:29:46 +0200 Subject: [PATCH 61/98] Fix NPE --- .../src/main/java/org/apache/maven/plugin/MojoExecution.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java b/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java index 5f6f0fd0dca8..095778b19979 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/MojoExecution.java @@ -159,7 +159,7 @@ public void setConfiguration( org.codehaus.plexus.util.xml.Xpp3Dom configuration public void setConfiguration( Dom configuration ) { - this.configuration = new org.codehaus.plexus.util.xml.Xpp3Dom( configuration ); + this.configuration = configuration != null ? new org.codehaus.plexus.util.xml.Xpp3Dom( configuration ) : null; } public String identify() From 2830be60293871c67f39d8b79f5a51727d5a0f50 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 21 Jun 2022 16:31:20 +0200 Subject: [PATCH 62/98] Add an @Experimental annotation to flag the api as experimental --- .../java/org/apache/maven/api/Artifact.java | 2 ++ .../java/org/apache/maven/api/Dependency.java | 2 ++ .../main/java/org/apache/maven/api/Event.java | 2 ++ .../java/org/apache/maven/api/EventType.java | 3 ++ .../java/org/apache/maven/api/Exclusion.java | 2 ++ .../org/apache/maven/api/JavaToolchain.java | 3 ++ .../java/org/apache/maven/api/Listener.java | 2 ++ .../org/apache/maven/api/LocalRepository.java | 2 ++ .../java/org/apache/maven/api/Metadata.java | 3 ++ .../org/apache/maven/api/MetadataStorage.java | 3 ++ .../org/apache/maven/api/MojoExecution.java | 2 ++ .../main/java/org/apache/maven/api/Node.java | 2 ++ .../org/apache/maven/api/NodeVisitor.java | 2 ++ .../java/org/apache/maven/api/Project.java | 2 ++ .../apache/maven/api/RemoteRepository.java | 2 ++ .../java/org/apache/maven/api/Repository.java | 2 ++ .../apache/maven/api/RepositoryMetadata.java | 3 ++ .../java/org/apache/maven/api/Service.java | 2 ++ .../java/org/apache/maven/api/Session.java | 2 ++ .../org/apache/maven/api/SessionData.java | 2 ++ .../java/org/apache/maven/api/Toolchain.java | 3 ++ .../org/apache/maven/api/plugin/Mojo.java | 2 ++ .../maven/api/plugin/MojoException.java | 2 ++ .../api/plugin/annotations/Component.java | 3 ++ .../maven/api/plugin/annotations/Execute.java | 3 ++ .../annotations/InstantiationStrategy.java | 3 ++ .../plugin/annotations/LifecyclePhase.java | 3 ++ .../maven/api/plugin/annotations/Mojo.java | 3 ++ .../api/plugin/annotations/Parameter.java | 3 ++ .../plugin/annotations/ResolutionScope.java | 3 ++ .../maven/api/services/ArtifactDeployer.java | 2 ++ .../services/ArtifactDeployerException.java | 3 ++ .../api/services/ArtifactDeployerRequest.java | 2 ++ .../maven/api/services/ArtifactFactory.java | 2 ++ .../api/services/ArtifactFactoryRequest.java | 2 ++ .../maven/api/services/ArtifactInstaller.java | 2 ++ .../services/ArtifactInstallerException.java | 3 ++ .../services/ArtifactInstallerRequest.java | 2 ++ .../maven/api/services/ArtifactManager.java | 2 ++ .../maven/api/services/ArtifactResolver.java | 2 ++ .../services/ArtifactResolverException.java | 3 ++ .../api/services/ArtifactResolverRequest.java | 2 ++ .../api/services/ArtifactResolverResult.java | 2 ++ .../maven/api/services/BaseRequest.java | 2 ++ .../api/services/DependencyCollector.java | 2 ++ .../DependencyCollectorException.java | 3 ++ .../services/DependencyCollectorRequest.java | 2 ++ .../services/DependencyCollectorResult.java | 2 ++ .../maven/api/services/DependencyFactory.java | 2 ++ .../services/DependencyFactoryRequest.java | 2 ++ .../api/services/DependencyResolver.java | 2 ++ .../services/DependencyResolverException.java | 3 ++ .../services/DependencyResolverRequest.java | 2 ++ .../services/DependencyResolverResult.java | 2 ++ .../api/services/LocalRepositoryManager.java | 2 ++ .../maven/api/services/MavenException.java | 3 ++ .../maven/api/services/ProjectBuilder.java | 2 ++ .../api/services/ProjectBuilderException.java | 3 ++ .../api/services/ProjectBuilderProblem.java | 3 ++ .../ProjectBuilderProblemSeverity.java | 3 ++ .../api/services/ProjectBuilderRequest.java | 2 ++ .../api/services/ProjectBuilderResult.java | 2 ++ .../api/services/ProjectBuilderSource.java | 3 ++ .../maven/api/services/ProjectManager.java | 2 ++ .../maven/api/services/RepositoryFactory.java | 2 ++ .../maven/api/services/ResolutionScope.java | 3 ++ .../maven/api/services/ToolchainFactory.java | 2 ++ .../maven/api/services/ToolchainManager.java | 2 ++ .../services/ToolchainManagerException.java | 3 ++ .../api/services/xml/ModelXmlFactory.java | 2 ++ .../api/services/xml/SettingsXmlFactory.java | 2 ++ .../services/xml/ToolchainsXmlFactory.java | 2 ++ .../maven/api/services/xml/XmlFactory.java | 2 ++ .../api/services/xml/XmlReaderException.java | 2 ++ .../api/services/xml/XmlReaderRequest.java | 2 ++ .../api/services/xml/XmlWriterException.java | 2 ++ .../api/services/xml/XmlWriterRequest.java | 3 ++ .../maven/api/annotations/Experimental.java | 34 +++++++++++++++++++ api/maven-api-model/src/main/mdo/model.vm | 2 ++ api/maven-api-settings/src/main/mdo/model.vm | 2 ++ api/maven-api-toolchain/src/main/mdo/model.vm | 2 ++ .../java/org/apache/maven/api/xml/Dom.java | 2 ++ 82 files changed, 222 insertions(+) create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index a336bdd5fb02..33ee2e2be588 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Immutable; @@ -28,6 +29,7 @@ /** * TODO: split between Coordinates / AttachedArtifact / ResolvedArtifact ? */ +@Experimental @Immutable public interface Artifact { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java index 1dde0f9826e0..33603a41f380 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -19,12 +19,14 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; import org.apache.maven.api.annotations.Immutable; import java.util.Collection; +@Experimental @Immutable public interface Dependency { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java index b606baba4a85..f22f3d4cfbe4 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.util.Optional; @@ -28,6 +29,7 @@ * Such events can be listened to using {@link Listener}s objects * registered in the {@link Session}. */ +@Experimental public interface Event { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java index e8a7fda538a9..fd4e233b0e55 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java @@ -19,6 +19,8 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * The possible types of execution events. * @@ -26,6 +28,7 @@ * we need to align on one strategy * see also {@link MetadataStorage} and {@link org.apache.maven.api.services.ResolutionScope} */ +@Experimental public enum EventType { ProjectDiscoveryStarted, diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java index 11922c4f0802..5786196a88eb 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java @@ -19,8 +19,10 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nullable; +@Experimental public interface Exclusion { @Nullable diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java index d863e6f81b09..b97014bcbd3f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java @@ -19,6 +19,9 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + +@Experimental public interface JavaToolchain extends Toolchain { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java index d2c462339a57..b71801e5b426 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java @@ -20,11 +20,13 @@ */ import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; /** * A listener for session events. */ +@Experimental @FunctionalInterface @Consumer public interface Listener { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java index 5738af40adce..4744dc8f25af 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java @@ -21,8 +21,10 @@ import java.nio.file.Path; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; +@Experimental public interface LocalRepository extends Repository { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java index ec4a9b15dca2..af1eebcf6402 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * TODO: investigate removing the Metadata api completely */ +@Experimental public interface Metadata { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java index ed667243ba85..d7596ccee194 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * Storage location for metadata */ +@Experimental public enum MetadataStorage { GROUP, diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java index db526a7a4488..053a1e98b7aa 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java @@ -19,10 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Plugin; +@Experimental public interface MojoExecution { @Nonnull diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java index 3c4ae402f0b0..9ce266c56a5f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import java.util.List; @@ -29,6 +30,7 @@ /** * Represents a dependency node within a Maven project's dependency collector. */ +@Experimental @Immutable public interface Node { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java index 9771748797f4..99ffe308c29b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java @@ -21,6 +21,7 @@ import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; /** @@ -29,6 +30,7 @@ * @author Pim Moerenhout * @since 0.12 */ +@Experimental @Consumer public interface NodeVisitor { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java index 6ebd95f0bddd..20f1612a4a0f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; @@ -30,6 +31,7 @@ /** * Interface representing a Maven project. */ +@Experimental public interface Project { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java index 399c6d8c7527..7482d07b4514 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java @@ -19,8 +19,10 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; +@Experimental public interface RemoteRepository extends Repository { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java index 2f2d651199ed..abccc7165f8c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java @@ -19,8 +19,10 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; +@Experimental public interface Repository { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java index e45a31e6954a..2a8e50ac47df 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java @@ -19,6 +19,9 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + +@Experimental public interface RepositoryMetadata extends Metadata { } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java index 98623e04bb44..afdbb4f2a41a 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.ThreadSafe; /** @@ -29,6 +30,7 @@ * * @see Session#getService(Class) */ +@Experimental @ThreadSafe public interface Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index f5e6bad7efd9..837a1605e020 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.ThreadSafe; @@ -36,6 +37,7 @@ /** * The session to install / deploy / resolve artifacts and dependencies. */ +@Experimental @ThreadSafe public interface Session { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java index 56f0289510ac..9b0b0ed64323 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; import org.apache.maven.api.annotations.Provider; @@ -37,6 +38,7 @@ * * @see Session#getData() */ +@Experimental @ThreadSafe @Provider public interface SessionData { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java index 51dcb3b62459..04077850e792 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java @@ -21,9 +21,12 @@ import java.util.Map; +import org.apache.maven.api.annotations.Experimental; + /** * Toolchain interface. */ +@Experimental public interface Toolchain { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java index fe94753b27c0..4b73614ee321 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java @@ -20,6 +20,7 @@ */ import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; /** * This interface forms the contract required for Mojos to interact with the Maven @@ -27,6 +28,7 @@ * It features an execute() method, which triggers the Mojo's build-process behavior, and can throw * a MojoException if error conditions occur.
*/ +@Experimental @FunctionalInterface @Consumer public interface Mojo { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java index 2d50ca42a780..61035fe033e0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java @@ -19,11 +19,13 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.services.MavenException; /** * An exception occurring during the execution of a plugin.
*/ +@Experimental public class MojoException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java index d5f89ed580cd..7f8e705fa437 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java @@ -26,6 +26,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.apache.maven.api.annotations.Experimental; + /** * Used to configure injection of Plexus components by * @@ -34,6 +36,7 @@ * @author Olivier Lamy * @since 3.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) @Target( { ElementType.FIELD } ) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java index 81ce2dfe71d7..f5e9ddb687d0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java @@ -26,12 +26,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.apache.maven.api.annotations.Experimental; + /** * Used if your Mojo needs to fork a lifecycle. * * @author Olivier Lamy * @since 3.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) @Target( ElementType.TYPE ) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java index 7cac629141dc..3eb84435eba8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java @@ -19,12 +19,15 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * Component instantiation strategy. * * @author Hervé Boutemy * @since 3.0 */ +@Experimental public enum InstantiationStrategy { PER_LOOKUP( "per-lookup" ), diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java index a2bee4d56715..43987eb6927e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java @@ -19,11 +19,14 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * Lifecycle phases. * @author Olivier Lamy * @since 3.0 */ +@Experimental public enum LifecyclePhase { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java index 79169a0b062d..d5a06de4d950 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java @@ -26,12 +26,15 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.apache.maven.api.annotations.Experimental; + /** * This annotation will mark your class as a Mojo (ie. goal in a Maven plugin). * * @author Olivier Lamy * @since 3.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) @Target( ElementType.TYPE ) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java index 6923a954296f..a846d1c1f3af 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java @@ -26,6 +26,8 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.apache.maven.api.annotations.Experimental; + /** * Used to configure your Mojo parameters to be injected by * @@ -38,6 +40,7 @@ * @author Olivier Lamy * @since 3.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) @Target( { ElementType.FIELD } ) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java index 5fe8862a7227..401431b19d48 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java @@ -19,6 +19,8 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * Dependencies resolution scopes available before * mojo execution. @@ -29,6 +31,7 @@ * @author Hervé Boutemy * @since 3.0 */ +@Experimental public enum ResolutionScope { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java index 9074451939ec..d835a274aa65 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java @@ -25,11 +25,13 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; /** * */ +@Experimental public interface ArtifactDeployer extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java index ca9d9c4a6709..19083d43dd89 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java @@ -19,10 +19,13 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * An artifact could not correctly being deployed. * */ +@Experimental public class ArtifactDeployerException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java index 4ac697459092..162d0a55a167 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.util.Collection; @@ -32,6 +33,7 @@ /** * A request for deploying one or more artifacts to a remote repository. */ +@Experimental public interface ArtifactDeployerRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java index ceaf0e957b21..140f8dbebcea 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java @@ -22,11 +22,13 @@ import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; /** * Service used to create {@link Artifact} objects. */ +@Experimental public interface ArtifactFactory extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java index e48d59900c7e..9b410af824e0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java @@ -19,12 +19,14 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.Session; import org.apache.maven.api.annotations.NotThreadSafe; +@Experimental @Immutable public interface ArtifactFactoryRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java index ecaab2c05e4e..88133f35779f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java @@ -25,10 +25,12 @@ import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; /** * @author Robert Scholte */ +@Experimental public interface ArtifactInstaller extends Service { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java index 18da90ab7493..4ebf173d292a 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * */ +@Experimental public class ArtifactInstallerException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java index 8a6847acf25e..5c66c6089de9 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.NotThreadSafe; @@ -33,6 +34,7 @@ /** * A request for installing one or more artifacts in the local repository. */ +@Experimental @Immutable public interface ArtifactInstallerRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java index e33d3edc9867..3e8e8b781c2b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java @@ -20,6 +20,7 @@ */ import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; @@ -29,6 +30,7 @@ import org.apache.maven.api.Artifact; import org.apache.maven.api.Metadata; +@Experimental public interface ArtifactManager extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java index 1d63362cd44e..d35cb2b691dc 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -22,10 +22,12 @@ import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; /** * Resolves the artifact, i.e download the file when required and attach it to the artifact */ +@Experimental public interface ArtifactResolver extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java index d5e442b1d5a7..fe34047c2027 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * */ +@Experimental public class ArtifactResolverException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java index 1d163889c88e..115e7d9096c0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; @@ -29,6 +30,7 @@ /** * A request for resolving an artifact. */ +@Experimental @Immutable public interface ArtifactResolverRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java index 9011405f3e1d..8df51371bf1b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java @@ -20,6 +20,7 @@ */ import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; /** * The Artifact Result @@ -27,6 +28,7 @@ * @author Robert Scholte * @since 3.0 */ +@Experimental public interface ArtifactResolverResult { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java index dd8b1046e359..fe3574a6f5cc 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.util.ArrayList; @@ -30,6 +31,7 @@ /** * Base class for requests. */ +@Experimental abstract class BaseRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java index fe08b1fabc59..89fa8ec44fbd 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java @@ -20,6 +20,7 @@ */ import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.Session; @@ -36,6 +37,7 @@ * @author Robert Scholte * @author Guillaume Nodet */ +@Experimental public interface DependencyCollector extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java index e04b557dad7b..86b715d535b0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java @@ -19,10 +19,13 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * Thrown in case of bad artifact descriptors, version ranges or other issues encountered during calculation of the * dependency graph. */ +@Experimental public class DependencyCollectorException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java index 02413590afcd..7b4a84c0d699 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; @@ -46,6 +47,7 @@ * * @see DependencyCollector#collect(DependencyCollectorRequest) */ +@Experimental @Immutable public interface DependencyCollectorRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java index 6020bffc15eb..67f606ba3f36 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java @@ -22,12 +22,14 @@ import java.util.List; import org.apache.maven.api.Node; +import org.apache.maven.api.annotations.Experimental; /** * The result of a dependency collection request. * * @see DependencyCollector#collect(DependencyCollectorRequest) */ +@Experimental public interface DependencyCollectorResult { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java index 4d479df6929c..fe3f192d6f34 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java @@ -23,8 +23,10 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; +@Experimental public interface DependencyFactory extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java index bbd501f7011a..20dd5587dd1b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; @@ -31,6 +32,7 @@ import org.apache.maven.api.Exclusion; import org.apache.maven.api.annotations.NotThreadSafe; +@Experimental @Immutable public interface DependencyFactoryRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java index 11e80be3c5a6..d70285dcd91e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java @@ -26,6 +26,7 @@ import org.apache.maven.api.Dependency; import org.apache.maven.api.Node; import org.apache.maven.api.Project; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; @@ -36,6 +37,7 @@ * @author Robert Scholte * @author Guillaume Nodet */ +@Experimental public interface DependencyResolver extends Service { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java index 74bc04e8b341..9ccdb737035d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * The Exception class in case a resolving does not work. */ +@Experimental public class DependencyResolverException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java index ed01ba6b5578..92da7b9e95f1 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.NotThreadSafe; @@ -42,6 +43,7 @@ /** * A request to collect and resolve a dependency graph. */ +@Experimental @Immutable public interface DependencyResolverRequest extends DependencyCollectorRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java index ff24cf61dc1e..27b63f6b7a90 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java @@ -22,12 +22,14 @@ import java.util.List; import org.apache.maven.api.Node; +import org.apache.maven.api.annotations.Experimental; /** * * @author Robert Scholte * */ +@Experimental public interface DependencyResolverResult { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java index abd7a282090e..f40f7d0f2b21 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java @@ -27,7 +27,9 @@ import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Service; import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +@Experimental public interface LocalRepositoryManager extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java index 7b8338744057..6f5350b98412 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java @@ -19,6 +19,9 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + +@Experimental public class MavenException extends RuntimeException { public MavenException() diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java index fb5c3c375bd1..47051a2fa95d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -20,6 +20,7 @@ */ import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; @@ -27,6 +28,7 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +@Experimental public interface ProjectBuilder extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java index 018938592e29..6b72cd6b2d1e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * The Exception class in case a resolving does not work. */ +@Experimental public class ProjectBuilderException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java index 4b32d5738504..1e0b1c0d0162 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java @@ -19,6 +19,8 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * Describes a problem that was encountered during settings building. A problem can either be an exception that was * thrown or a simple string message. In addition, a problem carries a hint about its source, e.g. the settings file @@ -27,6 +29,7 @@ * @author Benjamin Bentmann * @author Robert Scholte */ +@Experimental public interface ProjectBuilderProblem { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java index 4b40a51a1d53..1200538b9d75 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * The different severity levels for a problem, in decreasing order. */ +@Experimental public enum ProjectBuilderProblemSeverity { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java index f4b1d7db7f90..92de03581804 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.NotThreadSafe; @@ -32,6 +33,7 @@ import static org.apache.maven.api.services.BaseRequest.nonNull; +@Experimental @Immutable public interface ProjectBuilderRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java index ea88e0272767..5548e665886a 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; @@ -27,6 +28,7 @@ import org.apache.maven.api.Project; +@Experimental public interface ProjectBuilderResult { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java index fd8c50d5b989..2c5c18188ddf 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java @@ -22,6 +22,9 @@ import java.io.IOException; import java.io.InputStream; +import org.apache.maven.api.annotations.Experimental; + +@Experimental public interface ProjectBuilderSource { InputStream getInputStream() throws IOException; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java index 4c94e649c816..08fc062c37fa 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -20,6 +20,7 @@ */ import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import java.nio.file.Path; @@ -36,6 +37,7 @@ /** * Interface to manage the project during its lifecycle */ +@Experimental public interface ProjectManager extends Service { /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java index d641fbae19e3..5b36b41b2e21 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java @@ -24,9 +24,11 @@ import org.apache.maven.api.LocalRepository; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Repository; +@Experimental public interface RepositoryFactory extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java index 3ff928c0b52d..e3059b81f681 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java @@ -19,11 +19,14 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * Resolution scope * TODO: merge this with {@link org.apache.maven.api.plugin.annotations.ResolutionScope} * TODO: should this simply be an EnumSet instead ? */ +@Experimental public enum ResolutionScope { Compile, diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java index 4d61cfc1e0ff..3c079011d355 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java @@ -20,7 +20,9 @@ */ import org.apache.maven.api.annotations.Consumer; +import org.apache.maven.api.annotations.Experimental; +@Experimental @Consumer public interface ToolchainFactory { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java index 8f83fb3dbd78..a6f637110923 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java @@ -25,7 +25,9 @@ import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Toolchain; +import org.apache.maven.api.annotations.Experimental; +@Experimental public interface ToolchainManager extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java index 727e66d5967c..845ea8fad2ff 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java @@ -19,9 +19,12 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; + /** * The Exception class in case a resolving does not work. */ +@Experimental public class ToolchainManagerException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java index 668d139ba62a..373522fbd149 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java @@ -19,8 +19,10 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.model.Model; +@Experimental public interface ModelXmlFactory extends XmlFactory { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java index 0bfee886d68c..2fdab67a8eba 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java @@ -19,8 +19,10 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.settings.Settings; +@Experimental public interface SettingsXmlFactory extends XmlFactory { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java index 8e14b16b0a59..5bbc42c865cf 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java @@ -19,8 +19,10 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.toolchain.PersistedToolchains; +@Experimental public interface ToolchainsXmlFactory extends XmlFactory { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java index a3b09151ed34..d21f256aff31 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java @@ -24,9 +24,11 @@ import java.io.Reader; import java.io.Writer; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.Service; +@Experimental public interface XmlFactory extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java index b5cd94ce0202..716c812534fd 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java @@ -19,11 +19,13 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.services.MavenException; /** * */ +@Experimental public class XmlReaderException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java index 4bb71c238ace..20f7f621162b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java @@ -24,10 +24,12 @@ import java.net.URL; import java.nio.file.Path; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.NotThreadSafe; +@Experimental @Immutable public interface XmlReaderRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java index 6ac5f4cf63cb..80fde8d59c0d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java @@ -19,11 +19,13 @@ * under the License. */ +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.services.MavenException; /** * */ +@Experimental public class XmlWriterException extends MavenException { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java index d504f44cb212..de225a1236fd 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java @@ -22,6 +22,9 @@ import java.io.OutputStream; import java.io.Writer; +import org.apache.maven.api.annotations.Experimental; + +@Experimental public interface XmlWriterRequest { diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java new file mode 100644 index 000000000000..b9ae1cf19708 --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java @@ -0,0 +1,34 @@ +package org.apache.maven.api.annotations; + +/* + * 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. + */ + +import java.lang.annotation.Documented; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; + +/** + * This annotation tags types that are part of an experimental API. + * Classes or methods annotated with this annotation may be changed / removed without notice. + */ +@Documented +@Retention( RetentionPolicy.CLASS ) +public @interface Experimental +{ +} diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 95967c58b355..4eb6f450672f 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -39,6 +39,7 @@ #set ( $dummy = $imports.add( "java.util.Collections" ) ) #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Experimental" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) @@ -94,6 +95,7 @@ import $imp; * ${line.trim()} #end */ +@Experimental @Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) diff --git a/api/maven-api-settings/src/main/mdo/model.vm b/api/maven-api-settings/src/main/mdo/model.vm index 95967c58b355..4eb6f450672f 100644 --- a/api/maven-api-settings/src/main/mdo/model.vm +++ b/api/maven-api-settings/src/main/mdo/model.vm @@ -39,6 +39,7 @@ #set ( $dummy = $imports.add( "java.util.Collections" ) ) #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Experimental" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) @@ -94,6 +95,7 @@ import $imp; * ${line.trim()} #end */ +@Experimental @Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) diff --git a/api/maven-api-toolchain/src/main/mdo/model.vm b/api/maven-api-toolchain/src/main/mdo/model.vm index 95967c58b355..4eb6f450672f 100644 --- a/api/maven-api-toolchain/src/main/mdo/model.vm +++ b/api/maven-api-toolchain/src/main/mdo/model.vm @@ -39,6 +39,7 @@ #set ( $dummy = $imports.add( "java.util.Collections" ) ) #set ( $dummy = $imports.add( "java.util.HashMap" ) ) #set ( $dummy = $imports.add( "java.util.Map" ) ) + #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Experimental" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Generated" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Immutable" ) ) #set ( $dummy = $imports.add( "org.apache.maven.api.annotations.Nonnull" ) ) @@ -94,6 +95,7 @@ import $imp; * ${line.trim()} #end */ +@Experimental @Generated @ThreadSafe @Immutable public class ${class.name} #if ( $class.superClass ) diff --git a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java index eade36e995de..357a307fea78 100644 --- a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java +++ b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java @@ -22,11 +22,13 @@ import java.util.List; import java.util.Map; +import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; import org.apache.maven.api.annotations.ThreadSafe; +@Experimental @ThreadSafe @Immutable public interface Dom { From 065afe96c2d03f5588e8c99c103b14fee03edc2a Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 22 Jun 2022 16:39:27 +0200 Subject: [PATCH 63/98] Make sure we don't do reflection on sun.nio.fs.UnixPath class --- .../project/interpolation/StringSearchModelInterpolator.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java b/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java index 8dc8784b12e6..71da2ed3b00c 100644 --- a/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java +++ b/maven-compat/src/main/java/org/apache/maven/project/interpolation/StringSearchModelInterpolator.java @@ -343,7 +343,8 @@ else if ( Map.class.isAssignableFrom( type ) ) private boolean isQualifiedForInterpolation( Class cls ) { - return !cls.getPackage().getName().startsWith( "java" ); + return !cls.getPackage().getName().startsWith( "java" ) + && !cls.getPackage().getName().startsWith( "sun.nio.fs" ); } private boolean isQualifiedForInterpolation( Field field, Class fieldType ) From 4f772a81251f297af17189a3b17eb6073a0caf37 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 23 Jun 2022 10:15:48 +0200 Subject: [PATCH 64/98] Remove commented plugin --- plexus-utils/pom.xml | 21 --------------------- 1 file changed, 21 deletions(-) diff --git a/plexus-utils/pom.xml b/plexus-utils/pom.xml index dd201e11642b..638369440f47 100644 --- a/plexus-utils/pom.xml +++ b/plexus-utils/pom.xml @@ -79,27 +79,6 @@ under the License. - - - - - - - - - - - - - - - - - - - - - From 3b53bcc2ec2dd76398f16ca3e24b7bf1015ed07c Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 24 Jun 2022 12:06:48 +0200 Subject: [PATCH 65/98] Add the prompter api --- .../apache/maven/api/services/Prompter.java | 101 ++++++++++++++++++ .../maven/api/services/PrompterException.java | 40 +++++++ .../maven/internal/impl/DefaultPrompter.java | 87 +++++++++++++++ .../maven/internal/impl/DefaultSession.java | 15 ++- .../internal/impl/DefaultSessionFactory.java | 8 +- .../apache/maven/internal/impl/TestApi.java | 7 +- 6 files changed, 252 insertions(+), 6 deletions(-) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPrompter.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java new file mode 100644 index 000000000000..6d4816a08a9a --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java @@ -0,0 +1,101 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; + +@Experimental +public interface Prompter extends Service +{ + /** + * Prompts the user for a string. + * + * @param message the message to display to the user + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + default String prompt( String message ) + throws PrompterException + { + return prompt( message, null, null ); + } + + /** + * Prompts the user for a string using a default value. + * + * @param message the message to display + * @param defaultReply the default reply value + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + default String prompt( String message, String defaultReply ) + throws PrompterException + { + return prompt( message, null, defaultReply ); + } + + /** + * Prompts the user for a string using a list of possible values. + * + * @param message the message to display + * @param possibleValues the list of possible values + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + default String prompt( String message, List possibleValues ) + throws PrompterException + { + return prompt( message, possibleValues, null ); + } + + /** + * Prompts the user for a string using a list of possible values and a default reply. + * + * @param message the message to display + * @param possibleValues the list of possible values + * @param defaultReply the default reply value + * @return the string entered by the user + * @throws PrompterException if an exception occurs + */ + String prompt( String message, List possibleValues, String defaultReply ) + throws PrompterException; + + /** + * Prompts the user for a password. + * + * @param message the message to display + * @return the password entered by the user + * @throws PrompterException if an exception occurs + */ + String promptForPassword( String message ) + throws PrompterException; + + /** + * Displays a message to the user. + * + * @param message the message to display + * @throws PrompterException if an exception occurs + */ + void showMessage( String message ) + throws PrompterException; +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java new file mode 100644 index 000000000000..6c3fbd3e4911 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java @@ -0,0 +1,40 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class in case a the prompter can not perform a call. + */ +@Experimental +public class PrompterException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public PrompterException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPrompter.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPrompter.java new file mode 100644 index 000000000000..e1e87f3e088c --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultPrompter.java @@ -0,0 +1,87 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.lang.reflect.Method; +import java.util.List; + +import org.apache.maven.api.services.Prompter; +import org.apache.maven.api.services.PrompterException; +import org.codehaus.plexus.PlexusContainer; + +public class DefaultPrompter implements Prompter +{ + + private static final String PROMPTER_CLASS = "org.codehaus.plexus.components.interactivity.Prompter"; + private final PlexusContainer container; + + public DefaultPrompter( PlexusContainer container ) + { + this.container = container; + } + + @Override + public String prompt( String message, List possibleValues, String defaultReply ) throws PrompterException + { + try + { + Class clazz = container.getContainerRealm().loadClass( PROMPTER_CLASS ); + Object instance = container.lookup( clazz ); + Method method = clazz.getMethod( "prompt", String.class, List.class, String.class ); + return (String) method.invoke( instance, message, possibleValues, defaultReply ); + } + catch ( Exception e ) + { + throw new PrompterException( "Unable to call prompter", e ); + } + } + + @Override + public String promptForPassword( String message ) throws PrompterException + { + try + { + Class clazz = container.getContainerRealm().loadClass( PROMPTER_CLASS ); + Object instance = container.lookup( clazz ); + Method method = clazz.getMethod( "promptForPassword", String.class ); + return (String) method.invoke( instance, message ); + } + catch ( Exception e ) + { + throw new PrompterException( "Unable to call prompter", e ); + } + } + + @Override + public void showMessage( String message ) throws PrompterException + { + try + { + Class clazz = container.getContainerRealm().loadClass( PROMPTER_CLASS ); + Object instance = container.lookup( clazz ); + Method method = clazz.getMethod( "showMessage", String.class ); + method.invoke( instance, message ); + } + catch ( Exception e ) + { + throw new PrompterException( "Unable to call prompter", e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index c9f0961af92b..ea4436828826 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -47,6 +47,7 @@ import org.apache.maven.api.services.LocalRepositoryManager; import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectManager; +import org.apache.maven.api.services.Prompter; import org.apache.maven.api.services.RepositoryFactory; import org.apache.maven.api.services.ToolchainManager; import org.apache.maven.api.services.xml.ModelXmlFactory; @@ -57,6 +58,7 @@ import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.MavenSession; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.codehaus.plexus.PlexusContainer; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; @@ -75,13 +77,15 @@ public class DefaultSession extends AbstractSession private final DefaultToolchainManagerPrivate toolchainManagerPrivate; private final ArtifactManager artifactManager = new DefaultArtifactManager(); private final ProjectManager projectManager = new DefaultProjectManager( artifactManager ); + private final PlexusContainer container; public DefaultSession( @Nonnull MavenSession session, @Nonnull RepositorySystem repositorySystem, @Nullable List repositories, @Nonnull org.apache.maven.project.ProjectBuilder projectBuilder, @Nonnull MavenRepositorySystem mavenRepositorySystem, - @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate ) + @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate, + @Nonnull PlexusContainer container ) { this.mavenSession = nonNull( session ); this.session = mavenSession.getRepositorySession(); @@ -93,6 +97,7 @@ public DefaultSession( @Nonnull MavenSession session, this.projectBuilder = projectBuilder; this.mavenRepositorySystem = mavenRepositorySystem; this.toolchainManagerPrivate = toolchainManagerPrivate; + this.container = container; } MavenSession getMavenSession() @@ -199,7 +204,7 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) MavenSession newSession = new MavenSession( mavenSession.getContainer(), repoSession, mavenSession.getRequest(), mavenSession.getResult() ); return new DefaultSession( newSession, repositorySystem, - repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container ); } @Nonnull @@ -207,7 +212,7 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) public Session withRemoteRepositories( @Nonnull List repositories ) { return new DefaultSession( mavenSession, repositorySystem, - repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container ); } @Nonnull @@ -279,6 +284,10 @@ else if ( clazz == ToolchainsXmlFactory.class ) { return (T) new DefaultToolchainsXmlFactory(); } + else if ( clazz == Prompter.class ) + { + return (T) new DefaultPrompter( container ); + } throw new NoSuchElementException( clazz.getName() ); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java index 1bc454809c20..9b939731db29 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -28,6 +28,7 @@ import org.apache.maven.execution.MavenSession; import org.apache.maven.project.ProjectBuilder; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.codehaus.plexus.PlexusContainer; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.SessionData; @@ -39,17 +40,20 @@ public class DefaultSessionFactory private final org.apache.maven.project.ProjectBuilder projectBuilder; private final MavenRepositorySystem mavenRepositorySystem; private final DefaultToolchainManagerPrivate toolchainManagerPrivate; + private final PlexusContainer plexusContainer; @Inject public DefaultSessionFactory( RepositorySystem repositorySystem, ProjectBuilder projectBuilder, MavenRepositorySystem mavenRepositorySystem, - DefaultToolchainManagerPrivate toolchainManagerPrivate ) + DefaultToolchainManagerPrivate toolchainManagerPrivate, + PlexusContainer plexusContainer ) { this.repositorySystem = repositorySystem; this.projectBuilder = projectBuilder; this.mavenRepositorySystem = mavenRepositorySystem; this.toolchainManagerPrivate = toolchainManagerPrivate; + this.plexusContainer = plexusContainer; } public Session getSession( MavenSession mavenSession ) @@ -70,6 +74,6 @@ private Session newSession( MavenSession mavenSession ) { return new DefaultSession( mavenSession, repositorySystem, null, - projectBuilder, mavenRepositorySystem, toolchainManagerPrivate ); + projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, plexusContainer ); } } diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index 957f40473009..c49850d7fb9d 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -37,6 +37,7 @@ import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; +import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.testing.PlexusTest; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; @@ -68,6 +69,9 @@ public class TestApi @Inject DefaultToolchainManagerPrivate toolchainManagerPrivate; + @Inject + PlexusContainer plexusContainer; + @BeforeEach void setup() { @@ -76,7 +80,8 @@ void setup() MavenSession ms = new MavenSession( null, rss, mer, null ); DefaultSession session = new DefaultSession( ms, repositorySystem, Collections.emptyList(), projectBuilder, - mavenRepositorySystem, toolchainManagerPrivate ); + mavenRepositorySystem, toolchainManagerPrivate, + plexusContainer ); DefaultLocalRepository localRepository = new DefaultLocalRepository( new LocalRepository( "target/test-classes/apiv4-repo" ) ); org.apache.maven.api.RemoteRepository remoteRepository = session.getRemoteRepository( From 8958f05171b715f2dd7ee95a5b37a6ca6184b6f4 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 24 Jun 2022 12:42:27 +0200 Subject: [PATCH 66/98] Add the message builder to the API --- .../maven/api/services/MessageBuilder.java | 147 ++++++++++++++++++ .../api/services/MessageBuilderFactory.java | 69 ++++++++ .../internal/impl/DefaultMessageBuilder.java | 139 +++++++++++++++++ .../impl/DefaultMessageBuilderFactory.java | 60 +++++++ .../maven/internal/impl/DefaultSession.java | 5 + 5 files changed, 420 insertions(+) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java new file mode 100644 index 000000000000..67a9408711ad --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java @@ -0,0 +1,147 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Nonnull; + +/** + * Message builder that supports configurable styling. + * @see MessageBuilderFactory + */ +public interface MessageBuilder +{ + /** + * Append message content in success style. + * By default, bold green + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder success( Object message ); + + /** + * Append message content in warning style. + * By default, bold yellow + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder warning( Object message ); + + /** + * Append message content in failure style. + * By default, bold red + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder failure( Object message ); + + /** + * Append message content in strong style. + * By default, bold + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder strong( Object message ); + + /** + * Append message content in mojo style. + * By default, green + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder mojo( Object message ); + + /** + * Append message content in project style. + * By default, cyan + * @param message the message to append + * @return the current builder + */ + @Nonnull + MessageBuilder project( Object message ); + + // + // message building methods modelled after Ansi methods + // + /** + * Append content to the message buffer. + * @param value the content to append + * @param offset the index of the first {@code char} to append + * @param len the number of {@code char}s to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( char[] value, int offset, int len ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( char[] value ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @param start the starting index of the subsequence to be appended + * @param end the end index of the subsequence to be appended + * @return the current builder + */ + @Nonnull + MessageBuilder a( CharSequence value, int start, int end ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( CharSequence value ); + + /** + * Append content to the message buffer. + * @param value the content to append + * @return the current builder + */ + @Nonnull + MessageBuilder a( Object value ); + + /** + * Append newline to the message buffer. + * @return the current builder + */ + @Nonnull + MessageBuilder newline(); + + /** + * Append formatted content to the buffer. + * @see String#format(String, Object...) + * @param pattern a format string + * @param args arguments referenced by the format specifiers in the format string. + * @return the current builder + */ + @Nonnull + MessageBuilder format( String pattern, Object... args ); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java new file mode 100644 index 000000000000..e866b5f47054 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java @@ -0,0 +1,69 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A factory for {@link MessageBuilder}. + */ +@Experimental +public interface MessageBuilderFactory extends Service +{ + /** + * Checks if the underlying output does support styling or not. + * @return whether color styling is supported or not + */ + boolean isColorEnabled(); + + /** + * Returns the terminal width or -1 if not supported. + * @return the terminal width + */ + int getTerminalWidth(); + + /** + * Creates a new message builder. + * @return a new message builder + */ + @Nonnull + MessageBuilder builder(); + + /** + * Creates a new message builder backed by the given string builder. + * @param stringBuilder a string builder + * @return a new message builder + */ + @Nonnull + MessageBuilder builder( @Nonnull StringBuilder stringBuilder ); + + /** + * Creates a new message builder of the specified size. + * @param size the initial size of the message builder buffer + * @return a new message builder + */ + @Nonnull + default MessageBuilder builder( int size ) + { + return builder( new StringBuilder( size ) ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java new file mode 100644 index 000000000000..add99f7994e5 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java @@ -0,0 +1,139 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.MessageBuilder; + +@Experimental +public class DefaultMessageBuilder implements MessageBuilder +{ + private final @Nonnull org.apache.maven.shared.utils.logging.MessageBuilder delegate; + + public DefaultMessageBuilder( @Nonnull org.apache.maven.shared.utils.logging.MessageBuilder delegate ) + { + this.delegate = delegate; + } + + @Override + @Nonnull + public MessageBuilder success( Object o ) + { + delegate.success( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder warning( Object o ) + { + delegate.warning( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder failure( Object o ) + { + delegate.failure( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder strong( Object o ) + { + delegate.strong( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder mojo( Object o ) + { + delegate.mojo( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder project( Object o ) + { + delegate.project( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( char[] chars, int i, int i1 ) + { + delegate.a( chars, i, i1 ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( char[] chars ) + { + delegate.a( chars ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( CharSequence charSequence, int i, int i1 ) + { + delegate.a( charSequence, i, i1 ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( CharSequence charSequence ) + { + delegate.a( charSequence ); + return this; + } + + @Override + @Nonnull + public MessageBuilder a( Object o ) + { + delegate.a( o ); + return this; + } + + @Override + @Nonnull + public MessageBuilder newline() + { + delegate.newline(); + return this; + } + + @Override + @Nonnull + public MessageBuilder format( String s, Object... objects ) + { + delegate.format( s, objects ); + return this; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java new file mode 100644 index 000000000000..078ca08b15c6 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilderFactory.java @@ -0,0 +1,60 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Objects; + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.MessageBuilder; +import org.apache.maven.api.services.MessageBuilderFactory; +import org.apache.maven.shared.utils.logging.MessageUtils; + +@Experimental +public class DefaultMessageBuilderFactory implements MessageBuilderFactory +{ + + @Override + public boolean isColorEnabled() + { + return MessageUtils.isColorEnabled(); + } + + @Override + public int getTerminalWidth() + { + return MessageUtils.getTerminalWidth(); + } + + @Override + @Nonnull + public MessageBuilder builder() + { + return new DefaultMessageBuilder( MessageUtils.buffer() ); + } + + @Override + @Nonnull + public MessageBuilder builder( @Nonnull StringBuilder stringBuilder ) + { + return new DefaultMessageBuilder( MessageUtils.buffer( Objects.requireNonNull( stringBuilder ) ) ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index ea4436828826..50fd27d82b37 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -45,6 +45,7 @@ import org.apache.maven.api.services.DependencyFactory; import org.apache.maven.api.services.DependencyResolver; import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectManager; import org.apache.maven.api.services.Prompter; @@ -288,6 +289,10 @@ else if ( clazz == Prompter.class ) { return (T) new DefaultPrompter( container ); } + else if ( clazz == MessageBuilderFactory.class ) + { + return (T) new DefaultMessageBuilderFactory(); + } throw new NoSuchElementException( clazz.getName() ); } From 01cfd695be84f0a52f60c687f00ec1d6ddef0582 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 24 Jun 2022 15:31:03 +0200 Subject: [PATCH 67/98] Add a MessageBuilder.build() method --- .../org/apache/maven/api/services/MessageBuilder.java | 8 ++++++++ .../apache/maven/internal/impl/DefaultMessageBuilder.java | 7 +++++++ 2 files changed, 15 insertions(+) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java index 67a9408711ad..f309cd48170e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java @@ -144,4 +144,12 @@ public interface MessageBuilder */ @Nonnull MessageBuilder format( String pattern, Object... args ); + + /** + * Return the built message. + * @return the message + */ + @Nonnull + String build(); + } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java index add99f7994e5..088258f0116f 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMessageBuilder.java @@ -136,4 +136,11 @@ public MessageBuilder format( String s, Object... objects ) delegate.format( s, objects ); return this; } + + @Override + @Nonnull + public String build() + { + return delegate.toString(); + } } From e5496cc2d62c94a9f27a15360e4f6f25b5f490f9 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 30 Jun 2022 23:01:50 +0200 Subject: [PATCH 68/98] Fix performance issues --- .../apache/maven/api/model/InputLocation.java | 4 +--- api/maven-api-model/src/main/mdo/model.vm | 16 ++++++++++++---- .../model/transform/pull/BufferingParser.java | 5 ++++- 3 files changed, 17 insertions(+), 8 deletions(-) diff --git a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java index fef494a5e517..5aff705b024b 100644 --- a/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java +++ b/api/maven-api-model/src/main/java/org/apache/maven/api/model/InputLocation.java @@ -22,7 +22,6 @@ import java.io.Serializable; import java.util.Collection; import java.util.Collections; -import java.util.HashMap; import java.util.LinkedHashMap; import java.util.Map; @@ -69,8 +68,7 @@ public InputLocation( int lineNumber, int columnNumber, InputSource source, Map< this.lineNumber = lineNumber; this.columnNumber = columnNumber; this.source = source; - this.locations = locations != null - ? Collections.unmodifiableMap( new HashMap<>( locations ) ) : Collections.emptyMap(); + this.locations = ImmutableCollections.copy( locations ); } public int getLineNumber() diff --git a/api/maven-api-model/src/main/mdo/model.vm b/api/maven-api-model/src/main/mdo/model.vm index 4eb6f450672f..9b3c2382ed0e 100644 --- a/api/maven-api-model/src/main/mdo/model.vm +++ b/api/maven-api-model/src/main/mdo/model.vm @@ -482,11 +482,19 @@ public class ${class.name} return base; } #if ( $locationTracking ) - Map locations = new HashMap<>( this.locations != null ? this.locations : ( base != null ? base.locations : Collections.emptyMap() ) ); - InputLocation location = locations.remove( "" ); + Map locations = null; + InputLocation location = null; #foreach ( $field in $allFields ) - InputLocation ${field.name}Location = locations.remove( "${field.name}" ); + InputLocation ${field.name}Location = null; #end + if ( this.locations != null ) + { + locations = this.locations; + location = locations.remove( "" ); + #foreach ( $field in $allFields ) + ${field.name}Location = locations.remove( "${field.name}" ); + #end + } #end return new ${class.name}( #if ( $class == $root ) @@ -501,7 +509,7 @@ public class ${class.name} #end #end #if ( $locationTracking ) - locations, + locations != null ? locations : ( base != null ? base.locations : null ), #set ( $sep = "#if(${allFields.size()}>0),#end" ) location != null ? location : ( base != null ? base.location : null )${sep} #foreach ( $field in $allFields ) diff --git a/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java index e3662686aba4..cbdb65d21ba2 100644 --- a/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java +++ b/maven-model-transform/src/main/java/org/apache/maven/model/transform/pull/BufferingParser.java @@ -25,6 +25,7 @@ import java.util.ArrayDeque; import java.util.Deque; import java.util.Objects; +import java.util.regex.Pattern; import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -38,6 +39,8 @@ public class BufferingParser implements XmlPullParser { + private static final Pattern WHITESPACE_REGEX = Pattern.compile( "[ \r\t\n]+" ); + protected XmlPullParser xmlPullParser; protected Deque events; protected Event current; @@ -200,7 +203,7 @@ public boolean isWhitespace() throws XmlPullParserException { if ( current.event == TEXT || current.event == CDSECT ) { - return current.text.matches( "[ \r\t\n]+" ); + return WHITESPACE_REGEX.matcher( current.text ).matches(); } else if ( current.event == IGNORABLE_WHITESPACE ) { From 7cb78877e2f6265ad2f88af5e4d0224cf0af1311 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 1 Jul 2022 09:52:57 +0200 Subject: [PATCH 69/98] Remove unneeded MappingList and use the correct variable in the template --- .../org/apache/maven/model/MappingList.java | 75 ------------------- maven-model/src/main/mdo/model-v3.vm | 20 ++--- 2 files changed, 10 insertions(+), 85 deletions(-) delete mode 100644 maven-model/src/main/java/org/apache/maven/model/MappingList.java diff --git a/maven-model/src/main/java/org/apache/maven/model/MappingList.java b/maven-model/src/main/java/org/apache/maven/model/MappingList.java deleted file mode 100644 index 8f64c6bdc41b..000000000000 --- a/maven-model/src/main/java/org/apache/maven/model/MappingList.java +++ /dev/null @@ -1,75 +0,0 @@ -package org.apache.maven.model; - -/* - * 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. - */ - -import java.util.AbstractList; -import java.util.List; -import java.util.function.Function; - -class MappingList extends AbstractList -{ - private final List list; - private final Function mapper; - private final Function revMapper; - - MappingList( List list, Function mapper, Function revMapper ) - { - this.list = list; - this.mapper = mapper; - this.revMapper = revMapper; - } - - @Override - public T get( int index ) - { - return mapper.apply( list.get( index ) ); - } - - @Override - public int size() - { - return list.size(); - } - - @Override - public boolean add( T t ) - { - return list.add( revMapper.apply( t ) ); - } - - @Override - public T set( int index, T element ) - { - return mapper.apply( list.set( index, revMapper.apply( element ) ) ); - } - - @Override - public void add( int index, T element ) - { - list.add( index, revMapper.apply( element ) ); - } - - @Override - public T remove( int index ) - { - return mapper.apply( list.remove( index ) ); - } - -} diff --git a/maven-model/src/main/mdo/model-v3.vm b/maven-model/src/main/mdo/model-v3.vm index 4d293a3ec594..b6e33401b424 100644 --- a/maven-model/src/main/mdo/model-v3.vm +++ b/maven-model/src/main/mdo/model-v3.vm @@ -173,7 +173,7 @@ public class ${class.name} public ${type} ${pfx}${cap}() { #if ( $field.to != "String" && $field.type == "java.util.List" && $field.multiplicity == "*" ) - return new WrapperList<${field.to}, org.apache.maven.api.model.${field.to}>( + 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 == "*" ) @@ -251,13 +251,13 @@ public class ${class.name} #end public InputLocation getLocation( Object key ) { - org.apache.maven.api.model.InputLocation loc = getDelegate().getLocation( key ); + ${packageModelV4}.InputLocation loc = getDelegate().getLocation( key ); return loc != null ? new InputLocation( loc ) : null; } public void setLocation( Object key, InputLocation location ) { - update( org.apache.maven.api.model.${class.name}.newBuilder( getDelegate(), true ) + update( ${packageModelV4}.${class.name}.newBuilder( getDelegate(), true ) .location( key, location.toApiLocation() ).build() ); } @@ -273,14 +273,14 @@ public class ${class.name} #if ( $field.to && $field.multiplicity != "*" ) if ( oldDelegate == getDelegate().get${cap}() ) { - update( getDelegate().with${cap}( ( org.apache.maven.api.model.${field.to} ) newDelegate ) ); + 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 list = new ArrayList<>( getDelegate().get${cap}() ); - list.replaceAll( d -> d == oldDelegate ? ( org.apache.maven.api.model.${field.to} ) newDelegate : d ); + 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; } @@ -294,14 +294,14 @@ public class ${class.name} return false; } - public static List ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) + public static List<${packageModelV4}.${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV4( List<${class.name}> list ) { - return list != null ? new MappingList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; + return list != null ? new WrapperList<>( list, ${class.name}::getDelegate, ${class.name}::new ) : null; } - public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List list ) + public static List<${class.name}> ${Helper.uncapitalise(${class.name})}ToApiV3( List<${packageModelV4}.${class.name}> list ) { - return list != null ? new MappingList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null; + return list != null ? new WrapperList<>( list, ${class.name}::new, ${class.name}::getDelegate ) : null; } #foreach ( $cs in $class.getCodeSegments($version) ) From 6317b8c0ad468a4abdee47531d461755ff051d0a Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 11 Jul 2022 10:03:39 +0200 Subject: [PATCH 70/98] Add suggested changes to the Mojo api --- .../org/apache/maven/api/plugin/annotations/Component.java | 2 +- .../java/org/apache/maven/api/plugin/annotations/Mojo.java | 4 ++-- .../org/apache/maven/api/plugin/annotations/Parameter.java | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java index 7f8e705fa437..86457208a575 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java @@ -39,7 +39,7 @@ @Experimental @Documented @Retention( RetentionPolicy.CLASS ) -@Target( { ElementType.FIELD } ) +@Target( { ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER } ) @Inherited public @interface Component { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java index d5a06de4d950..066cbd754e9d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java @@ -90,8 +90,8 @@ boolean requiresOnline() default false; /** - * own configurator class. - * @return own configurator class + * configurator bean name. + * @return the configurator bean name */ String configurator() default ""; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java index a846d1c1f3af..ab07f317617b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java @@ -43,7 +43,7 @@ @Experimental @Documented @Retention( RetentionPolicy.CLASS ) -@Target( { ElementType.FIELD } ) +@Target( { ElementType.FIELD, ElementType.METHOD } ) @Inherited public @interface Parameter { From 50e5788761f36082cf0ae0b5534b394322c12b84 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 11 Jul 2022 10:03:54 +0200 Subject: [PATCH 71/98] Change @since javadoc tag to 4.0 --- .../src/main/java/org/apache/maven/api/plugin/Mojo.java | 2 ++ .../main/java/org/apache/maven/api/plugin/MojoException.java | 1 + .../org/apache/maven/api/plugin/annotations/Component.java | 3 +-- .../java/org/apache/maven/api/plugin/annotations/Execute.java | 3 +-- .../maven/api/plugin/annotations/InstantiationStrategy.java | 3 +-- .../apache/maven/api/plugin/annotations/LifecyclePhase.java | 4 ++-- .../java/org/apache/maven/api/plugin/annotations/Mojo.java | 3 +-- .../org/apache/maven/api/plugin/annotations/Parameter.java | 3 +-- .../apache/maven/api/plugin/annotations/ResolutionScope.java | 3 +-- 9 files changed, 11 insertions(+), 14 deletions(-) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java index 4b73614ee321..a6217bff2a96 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Mojo.java @@ -27,6 +27,8 @@ * infrastructure.
* It features an execute() method, which triggers the Mojo's build-process behavior, and can throw * a MojoException if error conditions occur.
+ * + * @since 4.0 */ @Experimental @FunctionalInterface @Consumer diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java index 61035fe033e0..81daca08bb8d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java @@ -24,6 +24,7 @@ /** * An exception occurring during the execution of a plugin.
+ * @since 4.0 */ @Experimental public class MojoException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java index 86457208a575..f963dfa98ca5 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Component.java @@ -33,8 +33,7 @@ * * MavenPluginManager.getConfiguredMojo(...). * - * @author Olivier Lamy - * @since 3.0 + * @since 4.0 */ @Experimental @Documented diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java index f5e9ddb687d0..e4f870786a26 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Execute.java @@ -31,8 +31,7 @@ /** * Used if your Mojo needs to fork a lifecycle. * - * @author Olivier Lamy - * @since 3.0 + * @since 4.0 */ @Experimental @Documented diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java index 3eb84435eba8..c5cfc75ec64e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/InstantiationStrategy.java @@ -24,8 +24,7 @@ /** * Component instantiation strategy. * - * @author Hervé Boutemy - * @since 3.0 + * @since 4.0 */ @Experimental public enum InstantiationStrategy diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java index 43987eb6927e..84c567b4dcdf 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/LifecyclePhase.java @@ -23,8 +23,8 @@ /** * Lifecycle phases. - * @author Olivier Lamy - * @since 3.0 + * + * @since 4.0 */ @Experimental public enum LifecyclePhase diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java index 066cbd754e9d..588a64fba837 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java @@ -31,8 +31,7 @@ /** * This annotation will mark your class as a Mojo (ie. goal in a Maven plugin). * - * @author Olivier Lamy - * @since 3.0 + * @since 4.0 */ @Experimental @Documented diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java index ab07f317617b..27ada3d2a6b2 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Parameter.java @@ -37,8 +37,7 @@ * container: this annotation is only effective on fields of the Mojo class itself, nested bean injection * requires Sisu or JSR330 annotations. * - * @author Olivier Lamy - * @since 3.0 + * @since 4.0 */ @Experimental @Documented diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java index 401431b19d48..6c93c6c7255a 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java @@ -28,8 +28,7 @@ * Important note: The {@code id} values of this enum correspond to constants of * {@code org.apache.maven.artifact.Artifact} class and MUST BE KEPT IN SYNC. * - * @author Hervé Boutemy - * @since 3.0 + * @since 4.0 */ @Experimental public enum ResolutionScope From bcbb751a0a03953d70654958e4ae3211845a87a7 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 13 Jul 2022 21:34:30 +0200 Subject: [PATCH 72/98] Add Session.getPluginContext(Project) method --- .../java/org/apache/maven/api/Session.java | 15 +++++++- .../maven/internal/impl/DefaultSession.java | 38 ++++++++++++++++--- .../internal/impl/DefaultSessionFactory.java | 10 +++-- .../apache/maven/internal/impl/TestApi.java | 6 ++- 4 files changed, 59 insertions(+), 10 deletions(-) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index 837a1605e020..4062eb44cc51 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -26,6 +26,7 @@ import java.nio.file.Path; import java.util.Collection; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Optional; import java.util.Properties; @@ -60,13 +61,25 @@ public interface Session @Nonnull Properties getSystemProperties(); + /** + * Returns the plugin context for mojo being executed and the specified + * {@link Project}, never returns {@code null} as if context not present, creates it. + * + * Implementation note: while this method return type is {@link Map}, the returned map instance + * implements {@link java.util.concurrent.ConcurrentMap} as well. + * + * @throws org.apache.maven.api.services.MavenException if not called from the within a mojo execution + */ + @Nonnull + Map getPluginContext( @Nonnull Project project ); + /** * Retrieves the service for the interface * * @throws NoSuchElementException if the service could not be found */ @Nonnull - T getService( Class clazz ); + T getService( @Nonnull Class clazz ); /** * Creates a derived session using the given local repository. diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index 50fd27d82b37..f4fa0daefab7 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -21,6 +21,7 @@ import java.util.Collections; import java.util.List; +import java.util.Map; import java.util.NoSuchElementException; import java.util.Objects; import java.util.Properties; @@ -30,6 +31,7 @@ import org.apache.maven.RepositoryUtils; import org.apache.maven.api.Dependency; import org.apache.maven.api.LocalRepository; +import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Service; import org.apache.maven.api.Session; @@ -45,6 +47,7 @@ import org.apache.maven.api.services.DependencyFactory; import org.apache.maven.api.services.DependencyResolver; import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.MavenException; import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectManager; @@ -58,8 +61,13 @@ import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.MavenSession; +import org.apache.maven.execution.scope.internal.MojoExecutionScope; +import org.apache.maven.plugin.MojoExecution; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; import org.eclipse.aether.RepositorySystemSession; @@ -79,14 +87,17 @@ public class DefaultSession extends AbstractSession private final ArtifactManager artifactManager = new DefaultArtifactManager(); private final ProjectManager projectManager = new DefaultProjectManager( artifactManager ); private final PlexusContainer container; + private final MojoExecutionScope mojoExecutionScope; + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultSession( @Nonnull MavenSession session, @Nonnull RepositorySystem repositorySystem, @Nullable List repositories, @Nonnull org.apache.maven.project.ProjectBuilder projectBuilder, @Nonnull MavenRepositorySystem mavenRepositorySystem, @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate, - @Nonnull PlexusContainer container ) + @Nonnull PlexusContainer container, + @Nonnull MojoExecutionScope mojoExecutionScope ) { this.mavenSession = nonNull( session ); this.session = mavenSession.getRepositorySession(); @@ -99,6 +110,7 @@ public DefaultSession( @Nonnull MavenSession session, this.mavenRepositorySystem = mavenRepositorySystem; this.toolchainManagerPrivate = toolchainManagerPrivate; this.container = container; + this.mojoExecutionScope = mojoExecutionScope; } MavenSession getMavenSession() @@ -141,6 +153,22 @@ public Properties getSystemProperties() return mavenSession.getSystemProperties(); } + @Override + public Map getPluginContext( Project project ) + { + try + { + MojoExecution mojoExecution = container.lookup( MojoExecution.class ); + MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor(); + PluginDescriptor pluginDescriptor = mojoDescriptor.getPluginDescriptor(); + return mavenSession.getPluginContext( pluginDescriptor, ( ( DefaultProject ) project ).getProject() ); + } + catch ( ComponentLookupException e ) + { + throw new MavenException( "The PluginContext is only available during a mojo execution", e ); + } + } + @Nonnull @Override public SessionData getData() @@ -204,16 +232,16 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) .setLocalRepositoryManager( localRepositoryManager ); MavenSession newSession = new MavenSession( mavenSession.getContainer(), repoSession, mavenSession.getRequest(), mavenSession.getResult() ); - return new DefaultSession( newSession, repositorySystem, - repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container ); + return new DefaultSession( newSession, repositorySystem, repositories, + projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container, mojoExecutionScope ); } @Nonnull @Override public Session withRemoteRepositories( @Nonnull List repositories ) { - return new DefaultSession( mavenSession, repositorySystem, - repositories, projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container ); + return new DefaultSession( mavenSession, repositorySystem, repositories, + projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container, mojoExecutionScope ); } @Nonnull diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java index 9b939731db29..c894c4d8c3da 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -26,6 +26,7 @@ import org.apache.maven.api.Session; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.MavenSession; +import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.project.ProjectBuilder; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.codehaus.plexus.PlexusContainer; @@ -41,19 +42,22 @@ public class DefaultSessionFactory private final MavenRepositorySystem mavenRepositorySystem; private final DefaultToolchainManagerPrivate toolchainManagerPrivate; private final PlexusContainer plexusContainer; + private final MojoExecutionScope mojoExecutionScope; @Inject public DefaultSessionFactory( RepositorySystem repositorySystem, ProjectBuilder projectBuilder, MavenRepositorySystem mavenRepositorySystem, DefaultToolchainManagerPrivate toolchainManagerPrivate, - PlexusContainer plexusContainer ) + PlexusContainer plexusContainer, + MojoExecutionScope mojoExecutionScope ) { this.repositorySystem = repositorySystem; this.projectBuilder = projectBuilder; this.mavenRepositorySystem = mavenRepositorySystem; this.toolchainManagerPrivate = toolchainManagerPrivate; this.plexusContainer = plexusContainer; + this.mojoExecutionScope = mojoExecutionScope; } public Session getSession( MavenSession mavenSession ) @@ -73,7 +77,7 @@ public Session getSession( MavenSession mavenSession ) private Session newSession( MavenSession mavenSession ) { return new DefaultSession( - mavenSession, repositorySystem, null, - projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, plexusContainer ); + mavenSession, repositorySystem, null, projectBuilder, mavenRepositorySystem, + toolchainManagerPrivate, plexusContainer, mojoExecutionScope ); } } diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index c49850d7fb9d..b58087627aa7 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -35,6 +35,7 @@ import org.apache.maven.api.services.ProjectBuilderRequest; import org.apache.maven.api.services.RepositoryFactory; import org.apache.maven.bridge.MavenRepositorySystem; +import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.codehaus.plexus.PlexusContainer; @@ -72,6 +73,9 @@ public class TestApi @Inject PlexusContainer plexusContainer; + @Inject + MojoExecutionScope mojoExecutionScope; + @BeforeEach void setup() { @@ -81,7 +85,7 @@ void setup() DefaultSession session = new DefaultSession( ms, repositorySystem, Collections.emptyList(), projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, - plexusContainer ); + plexusContainer, mojoExecutionScope ); DefaultLocalRepository localRepository = new DefaultLocalRepository( new LocalRepository( "target/test-classes/apiv4-repo" ) ); org.apache.maven.api.RemoteRepository remoteRepository = session.getRemoteRepository( From 41cf7b3780373e88bfc5eab2b889f4e5c87395aa Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 13 Jul 2022 21:34:50 +0200 Subject: [PATCH 73/98] Runtime fixes for api v4 --- .../org/apache/maven/internal/impl/DefaultProject.java | 7 ++++++- .../maven/internal/impl/DefaultSessionFactory.java | 10 +--------- .../apache/maven/plugin/DefaultBuildPluginManager.java | 9 +-------- 3 files changed, 8 insertions(+), 18 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java index bd53ee239ea4..7ba41d61f372 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -37,6 +37,7 @@ import org.apache.maven.api.Project; import org.apache.maven.api.model.DependencyManagement; import org.apache.maven.api.model.Model; +import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.project.MavenProject; public class DefaultProject implements Project @@ -86,7 +87,11 @@ public String getVersion() @Override public Artifact getArtifact() { - return session.getArtifact( RepositoryUtils.toArtifact( project.getArtifact() ) ); + org.eclipse.aether.artifact.Artifact resolverArtifact = RepositoryUtils.toArtifact( project.getArtifact() ); + Artifact artifact = session.getArtifact( resolverArtifact ); + Path path = resolverArtifact.getFile() != null ? resolverArtifact.getFile().toPath() : null; + session.getService( ArtifactManager.class ).setPath( artifact, path ); + return artifact; } @Nonnull diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java index c894c4d8c3da..d8581d76ce90 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -63,15 +63,7 @@ public DefaultSessionFactory( RepositorySystem repositorySystem, public Session getSession( MavenSession mavenSession ) { SessionData data = mavenSession.getRepositorySession().getData(); - Session session = ( Session ) data.get( DefaultSession.class ); - if ( session == null ) - { - if ( ! data.set( DefaultSession.class, null, newSession( mavenSession ) ) ) - { - session = ( Session ) data.get( DefaultSession.class ); - } - } - return session; + return ( Session ) data.computeIfAbsent( DefaultSession.class, () -> newSession( mavenSession ) ); } private Session newSession( MavenSession mavenSession ) diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index 6f2256455fba..fddda494debc 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -143,14 +143,7 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) { MojoExecutionEvent mojoExecutionEvent = new MojoExecutionEvent( session, project, mojoExecution, mojo ); mojoExecutionListener.beforeMojoExecution( mojoExecutionEvent ); - if ( mojoDescriptor.isV4Api() ) - { - ( ( org.apache.maven.api.plugin.Mojo ) mojo ).execute(); - } - else - { - ( ( Mojo ) mojo ).execute(); - } + mojo.execute(); mojoExecutionListener.afterMojoExecutionSuccess( mojoExecutionEvent ); } catch ( ClassCastException e ) From 4e58a06d8439c75a4ab4d32e07f18615d994bdd0 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 19 Jul 2022 09:31:40 +0200 Subject: [PATCH 74/98] Add a VersionParser / Version / VersionRange to the new api, move ArtifactManager#isSnapshot to the VersionParser --- .../java/org/apache/maven/api/Session.java | 26 +++- .../java/org/apache/maven/api/Version.java | 40 ++++++ .../org/apache/maven/api/VersionRange.java | 46 +++++++ .../maven/api/services/ArtifactManager.java | 5 - .../maven/api/services/VersionParser.java | 59 +++++++++ .../api/services/VersionParserException.java | 40 ++++++ .../maven/internal/impl/AbstractSession.java | 18 ++- .../internal/impl/DefaultArtifactManager.java | 9 -- .../maven/internal/impl/DefaultSession.java | 27 +++- .../internal/impl/DefaultSessionFactory.java | 8 +- .../internal/impl/DefaultVersionParser.java | 122 ++++++++++++++++++ .../apache/maven/internal/impl/TestApi.java | 6 +- 12 files changed, 382 insertions(+), 24 deletions(-) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Version.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index 4062eb44cc51..6778008ebbe3 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -61,6 +61,13 @@ public interface Session @Nonnull Properties getSystemProperties(); + /** + * Returns the current maven version + * @return the maven version, never {@code null}. + */ + @Nonnull + String getMavenVersion(); + /** * Returns the plugin context for mojo being executed and the specified * {@link Project}, never returns {@code null} as if context not present, creates it. @@ -205,7 +212,7 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri /** * Shortcut for getService(ArtifactManager.class).isSnapshot(...) - * @see org.apache.maven.api.services.ArtifactManager#isSnapshot(String) + * @see org.apache.maven.api.services.VersionParser#isSnapshot(String) */ boolean isVersionSnapshot( @Nonnull String version ); @@ -260,4 +267,21 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata ); + /** + * Shortcut for getService(VersionParser.class).parseVersion(...) + * @see org.apache.maven.api.services.VersionParser#parseVersion(String) + * + * @throws org.apache.maven.api.services.VersionParserException if the parsing failed + */ + @Nonnull + Version parseVersion( @Nonnull String version ); + + /** + * Shortcut for getService(VersionParser.class).parseVersionRange(...) + * @see org.apache.maven.api.services.VersionParser#parseVersionRange(String) + * + * @throws org.apache.maven.api.services.VersionParserException if the parsing failed + */ + @Nonnull + VersionRange parseVersionRange( @Nonnull String versionRange ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java new file mode 100644 index 000000000000..ea409309c7be --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java @@ -0,0 +1,40 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A version. + */ +@Experimental +public interface Version + extends Comparable +{ + + /** + * Returns a string representation of this version. + * @return the string representation of this version + */ + @Nonnull + String toString(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java new file mode 100644 index 000000000000..83a730f840e3 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java @@ -0,0 +1,46 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * A range of versions. + */ +@Experimental +public interface VersionRange +{ + + /** + * Determines whether the specified version is contained within this range. + * + * @param version The version to test, must not be {@code null}. + * @return {@code true} if this range contains the specified version, {@code false} otherwise. + */ + boolean contains( @Nonnull Version version ); + + /** + * Returns a string representation of this version range + * @return the string representation of this version range + */ + @Nonnull + String toString(); +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java index 3e8e8b781c2b..a65d05fb61db 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java @@ -57,9 +57,4 @@ public interface ArtifactManager extends Service */ void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metadata ); - /** - * Checks whether a given artifact version is considered a {@code SNAPSHOT} or not. - */ - boolean isSnapshot( String version ); - } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java new file mode 100644 index 000000000000..bb4655416d6a --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java @@ -0,0 +1,59 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.Version; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Service interface to parse version and version ranges + */ +@Experimental +public interface VersionParser extends Service +{ + /** + * Parses the specified version string, for example "1.0". + * + * @param version The version string to parse, must not be {@code null}. + * @return The parsed version, never {@code null}. + * @throws VersionParserException If the string violates the syntax rules of this scheme. + */ + @Nonnull + Version parseVersion( @Nonnull String version ); + + /** + * Parses the specified version range specification, for example "[1.0,2.0)". + * + * @param range The range specification to parse, must not be {@code null}. + * @return The parsed version range, never {@code null}. + * @throws VersionParserException If the range specification violates the syntax rules of this scheme. + */ + @Nonnull + VersionRange parseVersionRange( @Nonnull String range ); + + /** + * Checks whether a given artifact version is considered a {@code SNAPSHOT} or not. + */ + boolean isSnapshot( @Nonnull String version ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java new file mode 100644 index 000000000000..fca94c6e51ae --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java @@ -0,0 +1,40 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class in case a resolving does not work. + */ +@Experimental +public class VersionParserException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public VersionParserException( String message, Exception e ) + { + super( message, e ); + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java index 2c5fe109589b..136bdbcb2f93 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java @@ -42,6 +42,8 @@ import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Session; +import org.apache.maven.api.Version; +import org.apache.maven.api.VersionRange; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Repository; import org.apache.maven.api.services.ArtifactDeployer; @@ -59,6 +61,7 @@ import org.apache.maven.api.services.DependencyResolverException; import org.apache.maven.api.services.LocalRepositoryManager; import org.apache.maven.api.services.RepositoryFactory; +import org.apache.maven.api.services.VersionParser; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.project.MavenProject; @@ -390,7 +393,7 @@ public Optional getArtifactPath( @Nonnull Artifact artifact ) @Override public boolean isVersionSnapshot( @Nonnull String version ) { - return getService( ArtifactManager.class ) + return getService( VersionParser.class ) .isSnapshot( version ); } @@ -495,4 +498,17 @@ public Path getPathForRemoteMetadata( RemoteRepository remote, Metadata metadata .getPathForRemoteMetadata( this, getLocalRepository(), remote, metadata ); } + @Override + public Version parseVersion( String version ) + { + return getService( VersionParser.class ) + .parseVersion( version ); + } + + @Override + public VersionRange parseVersionRange( String versionRange ) + { + return getService( VersionParser.class ) + .parseVersionRange( versionRange ); + } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java index 5b4ee5d0e5b0..54d9eaed37e4 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java @@ -28,7 +28,6 @@ import java.util.Optional; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.regex.Pattern; import org.apache.maven.api.Artifact; import org.apache.maven.api.Metadata; @@ -36,9 +35,6 @@ public class DefaultArtifactManager implements ArtifactManager { - private static final String SNAPSHOT = "SNAPSHOT"; - private static final Pattern SNAPSHOT_TIMESTAMP = Pattern.compile( "^(.*-)?([0-9]{8}\\.[0-9]{6}-[0-9]+)$" ); - private final Map paths = new ConcurrentHashMap<>(); private final Map> metadatas = new ConcurrentHashMap<>(); @@ -78,9 +74,4 @@ public void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metada metadatas.computeIfAbsent( artifact, a -> new CopyOnWriteArrayList<>() ).add( metadata ); } - @Override - public boolean isSnapshot( String version ) - { - return version.endsWith( SNAPSHOT ) || SNAPSHOT_TIMESTAMP.matcher( version ).matches(); - } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index f4fa0daefab7..7fd28a0ed890 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -54,6 +54,7 @@ import org.apache.maven.api.services.Prompter; import org.apache.maven.api.services.RepositoryFactory; import org.apache.maven.api.services.ToolchainManager; +import org.apache.maven.api.services.VersionParser; import org.apache.maven.api.services.xml.ModelXmlFactory; import org.apache.maven.api.services.xml.SettingsXmlFactory; import org.apache.maven.api.services.xml.ToolchainsXmlFactory; @@ -65,6 +66,7 @@ import org.apache.maven.plugin.MojoExecution; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; @@ -88,6 +90,7 @@ public class DefaultSession extends AbstractSession private final ProjectManager projectManager = new DefaultProjectManager( artifactManager ); private final PlexusContainer container; private final MojoExecutionScope mojoExecutionScope; + private final RuntimeInformation runtimeInformation; @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultSession( @Nonnull MavenSession session, @@ -97,7 +100,8 @@ public DefaultSession( @Nonnull MavenSession session, @Nonnull MavenRepositorySystem mavenRepositorySystem, @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate, @Nonnull PlexusContainer container, - @Nonnull MojoExecutionScope mojoExecutionScope ) + @Nonnull MojoExecutionScope mojoExecutionScope, + @Nonnull RuntimeInformation runtimeInformation ) { this.mavenSession = nonNull( session ); this.session = mavenSession.getRepositorySession(); @@ -111,6 +115,7 @@ public DefaultSession( @Nonnull MavenSession session, this.toolchainManagerPrivate = toolchainManagerPrivate; this.container = container; this.mojoExecutionScope = mojoExecutionScope; + this.runtimeInformation = runtimeInformation; } MavenSession getMavenSession() @@ -153,9 +158,17 @@ public Properties getSystemProperties() return mavenSession.getSystemProperties(); } + @Nonnull + @Override + public String getMavenVersion() + { + return runtimeInformation.getMavenVersion(); + } + @Override public Map getPluginContext( Project project ) { + nonNull( project, "project" ); try { MojoExecution mojoExecution = container.lookup( MojoExecution.class ); @@ -232,16 +245,16 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) .setLocalRepositoryManager( localRepositoryManager ); MavenSession newSession = new MavenSession( mavenSession.getContainer(), repoSession, mavenSession.getRequest(), mavenSession.getResult() ); - return new DefaultSession( newSession, repositorySystem, repositories, - projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container, mojoExecutionScope ); + return new DefaultSession( newSession, repositorySystem, repositories, projectBuilder, mavenRepositorySystem, + toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation ); } @Nonnull @Override public Session withRemoteRepositories( @Nonnull List repositories ) { - return new DefaultSession( mavenSession, repositorySystem, repositories, - projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, container, mojoExecutionScope ); + return new DefaultSession( mavenSession, repositorySystem, repositories, projectBuilder, mavenRepositorySystem, + toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation ); } @Nonnull @@ -321,6 +334,10 @@ else if ( clazz == MessageBuilderFactory.class ) { return (T) new DefaultMessageBuilderFactory(); } + else if ( clazz == VersionParser.class ) + { + return (T) new DefaultVersionParser(); + } throw new NoSuchElementException( clazz.getName() ); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java index d8581d76ce90..a7689a56a3d9 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -28,6 +28,7 @@ import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.project.ProjectBuilder; +import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.codehaus.plexus.PlexusContainer; import org.eclipse.aether.RepositorySystem; @@ -43,6 +44,7 @@ public class DefaultSessionFactory private final DefaultToolchainManagerPrivate toolchainManagerPrivate; private final PlexusContainer plexusContainer; private final MojoExecutionScope mojoExecutionScope; + private final RuntimeInformation runtimeInformation; @Inject public DefaultSessionFactory( RepositorySystem repositorySystem, @@ -50,7 +52,8 @@ public DefaultSessionFactory( RepositorySystem repositorySystem, MavenRepositorySystem mavenRepositorySystem, DefaultToolchainManagerPrivate toolchainManagerPrivate, PlexusContainer plexusContainer, - MojoExecutionScope mojoExecutionScope ) + MojoExecutionScope mojoExecutionScope, + RuntimeInformation runtimeInformation ) { this.repositorySystem = repositorySystem; this.projectBuilder = projectBuilder; @@ -58,6 +61,7 @@ public DefaultSessionFactory( RepositorySystem repositorySystem, this.toolchainManagerPrivate = toolchainManagerPrivate; this.plexusContainer = plexusContainer; this.mojoExecutionScope = mojoExecutionScope; + this.runtimeInformation = runtimeInformation; } public Session getSession( MavenSession mavenSession ) @@ -70,6 +74,6 @@ private Session newSession( MavenSession mavenSession ) { return new DefaultSession( mavenSession, repositorySystem, null, projectBuilder, mavenRepositorySystem, - toolchainManagerPrivate, plexusContainer, mojoExecutionScope ); + toolchainManagerPrivate, plexusContainer, mojoExecutionScope, runtimeInformation ); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java new file mode 100644 index 000000000000..376745fdcf25 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java @@ -0,0 +1,122 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.regex.Pattern; + +import org.apache.maven.api.Version; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.services.VersionParser; +import org.apache.maven.api.services.VersionParserException; +import org.apache.maven.artifact.versioning.ArtifactVersion; +import org.apache.maven.artifact.versioning.DefaultArtifactVersion; +import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException; + +import static org.apache.maven.artifact.versioning.VersionRange.createFromVersionSpec; +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultVersionParser implements VersionParser +{ + private static final String SNAPSHOT = "SNAPSHOT"; + private static final Pattern SNAPSHOT_TIMESTAMP = Pattern.compile( "^(.*-)?([0-9]{8}\\.[0-9]{6}-[0-9]+)$" ); + + @Override + public Version parseVersion( String version ) + { + return new DefaultVersion( new DefaultArtifactVersion( nonNull( version, "version" ) ) ); + } + + @Override + public VersionRange parseVersionRange( String range ) + { + try + { + return new DefaultVersionRange( createFromVersionSpec( nonNull( range, "version" ) ) ); + } + catch ( InvalidVersionSpecificationException e ) + { + throw new VersionParserException( "Unable to parse version range: " + range, e ); + } + } + + @Override + public boolean isSnapshot( String version ) + { + return version.endsWith( SNAPSHOT ) || SNAPSHOT_TIMESTAMP.matcher( version ).matches(); + } + + static class DefaultVersion implements Version + { + private final ArtifactVersion delegate; + + DefaultVersion( ArtifactVersion delegate ) + { + this.delegate = delegate; + } + + @Override + public int compareTo( Version o ) + { + if ( o instanceof DefaultVersion ) + { + return delegate.compareTo( ( ( DefaultVersion ) o ).delegate ); + } + else + { + return delegate.compareTo( new DefaultArtifactVersion( o.toString() ) ); + } + } + + @Override + public String toString() + { + return delegate.toString(); + } + } + + static class DefaultVersionRange implements VersionRange + { + private final org.apache.maven.artifact.versioning.VersionRange delegate; + + DefaultVersionRange( org.apache.maven.artifact.versioning.VersionRange delegate ) + { + this.delegate = delegate; + } + + @Override + public boolean contains( Version version ) + { + if ( version instanceof DefaultVersion ) + { + return delegate.containsVersion( ( ( DefaultVersion ) version ).delegate ); + } + else + { + return delegate.containsVersion( new DefaultArtifactVersion( version.toString() ) ); + } + } + + @Override + public String toString() + { + return delegate.toString(); + } + } +} diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index b58087627aa7..4b03dd74d291 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -37,6 +37,7 @@ import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; +import org.apache.maven.rtinfo.RuntimeInformation; import org.apache.maven.toolchain.DefaultToolchainManagerPrivate; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.testing.PlexusTest; @@ -76,6 +77,9 @@ public class TestApi @Inject MojoExecutionScope mojoExecutionScope; + @Inject + RuntimeInformation runtimeInformation; + @BeforeEach void setup() { @@ -85,7 +89,7 @@ void setup() DefaultSession session = new DefaultSession( ms, repositorySystem, Collections.emptyList(), projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, - plexusContainer, mojoExecutionScope ); + plexusContainer, mojoExecutionScope, runtimeInformation ); DefaultLocalRepository localRepository = new DefaultLocalRepository( new LocalRepository( "target/test-classes/apiv4-repo" ) ); org.apache.maven.api.RemoteRepository remoteRepository = session.getRemoteRepository( From aa1a1162ae1c0485da256f06979830285c058dd9 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 22 Jul 2022 08:31:13 +0200 Subject: [PATCH 75/98] Fix possible NPE --- .../DefaultLifecycleExecutionPlanCalculator.java | 11 ++++++++--- 1 file changed, 8 insertions(+), 3 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java index c352a079470e..68491936347d 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/DefaultLifecycleExecutionPlanCalculator.java @@ -562,11 +562,16 @@ private void injectLifecycleOverlay( Map> lifecycleM { for ( MojoExecution forkedExecution : forkedExecutions ) { - Dom forkedConfiguration = forkedExecution.getConfiguration().getDom(); + org.codehaus.plexus.util.xml.Xpp3Dom config = forkedExecution.getConfiguration(); - forkedConfiguration = phaseConfiguration.merge( forkedConfiguration ); + if ( config != null ) + { + Dom forkedConfiguration = config.getDom(); - forkedExecution.setConfiguration( forkedConfiguration ); + forkedConfiguration = phaseConfiguration.merge( forkedConfiguration ); + + forkedExecution.setConfiguration( forkedConfiguration ); + } } } } From 2003513a34e81bb9ad55b11f095a427b86339ed3 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 22 Jul 2022 09:54:22 +0200 Subject: [PATCH 76/98] Make sure plexus-utils embeds the Xpp3Dom and Xpp3DomBuilder classes --- maven-xml-impl/pom.xml | 6 +--- .../apache/maven/internal/xml/DomBuilder.java | 8 ++--- plexus-utils/pom.xml | 30 +++++++++++++++++++ 3 files changed, 35 insertions(+), 9 deletions(-) diff --git a/maven-xml-impl/pom.xml b/maven-xml-impl/pom.xml index 04e7c53af33b..6e4da2b40c55 100644 --- a/maven-xml-impl/pom.xml +++ b/maven-xml-impl/pom.xml @@ -39,11 +39,6 @@ under the License. maven-api-xml 4.0.0-alpha-1-SNAPSHOT
- - org.apache.maven - maven-api-model - 4.0.0-alpha-1-SNAPSHOT - org.eclipse.sisu org.eclipse.sisu.plexus @@ -52,6 +47,7 @@ under the License. org.codehaus.plexus plexus-utils 3.4.1 + provided diff --git a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java index 4d67730c2803..a4b14e728b6e 100644 --- a/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java +++ b/maven-xml-impl/src/main/java/org/apache/maven/internal/xml/DomBuilder.java @@ -21,7 +21,7 @@ import java.io.Reader; -import org.apache.maven.api.model.InputLocation; +//import org.apache.maven.api.model.InputLocation; import org.codehaus.plexus.util.xml.pull.MXParser; import org.codehaus.plexus.util.xml.pull.XmlPullParser; import org.codehaus.plexus.util.xml.pull.XmlPullParserException; @@ -77,14 +77,14 @@ public static Xpp3Dom build( XmlPullParser parser, boolean trim, LocationBuilder public static class LocationBuilder { - private final InputLocation location; + private final Object location; - public LocationBuilder( InputLocation location ) + public LocationBuilder( Object location ) { this.location = location; } - public InputLocation getLocation() + public Object getLocation() { return location; } diff --git a/plexus-utils/pom.xml b/plexus-utils/pom.xml index 638369440f47..13a0d994e86e 100644 --- a/plexus-utils/pom.xml +++ b/plexus-utils/pom.xml @@ -33,6 +33,20 @@ under the License. plexus-utils 4.0.0-alpha-1-SNAPSHOT + + + org.codehaus.plexus + plexus-utils + 3.4.2 + + + org.apache.maven + maven-xml-impl + ${project.version} + provided + + + @@ -61,6 +75,22 @@ under the License. org/codehaus/plexus/util/xml/Xpp3DomBuilder.class + + org.apache.maven + maven-api-xml + ${project.version} + jar + **/* + ${project.build.directory}/classes + + + org.apache.maven + maven-xml-impl + ${project.version} + jar + **/* + ${project.build.directory}/classes + **/*.java false From bec9c1cd30fc7f419b047050ff87c8b7f080127d Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 25 Jul 2022 09:20:15 +0200 Subject: [PATCH 77/98] Fix javadoc --- .../java/org/apache/maven/internal/impl/AbstractSession.java | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java index 136bdbcb2f93..8eb1cd8e45cb 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java @@ -386,9 +386,9 @@ public Optional getArtifactPath( @Nonnull Artifact artifact ) } /** - * Shortcut for getService(ArtifactManager.class).isSnapshot(...) + * Shortcut for getService(VersionParser.class).isSnapshot(...) * - * @see ArtifactManager#isSnapshot(String) + * @see VersionParser#isSnapshot(String) */ @Override public boolean isVersionSnapshot( @Nonnull String version ) From 05c6ba360dda72d65ddeb35ad68d7365c1f8401e Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Mon, 25 Jul 2022 09:20:45 +0200 Subject: [PATCH 78/98] Implement the Listener mechanism --- .../maven/internal/impl/EventSpyImpl.java | 150 ++++++++++++++++++ 1 file changed, 150 insertions(+) create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java b/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java new file mode 100644 index 000000000000..6759c5bf1268 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java @@ -0,0 +1,150 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Inject; +import javax.inject.Named; +import javax.inject.Singleton; + +import java.util.Collection; +import java.util.Optional; + +import org.apache.maven.api.Event; +import org.apache.maven.api.EventType; +import org.apache.maven.api.Listener; +import org.apache.maven.api.MojoExecution; +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.eventspy.EventSpy; +import org.apache.maven.execution.ExecutionEvent; + +@Named +@Singleton +public class EventSpyImpl implements EventSpy +{ + + private DefaultSessionFactory sessionFactory; + + @Inject + EventSpyImpl( DefaultSessionFactory sessionFactory ) + { + this.sessionFactory = sessionFactory; + } + + @Override + public void init( Context context ) throws Exception + { + } + + @Override + public void onEvent( Object arg ) throws Exception + { + if ( arg instanceof ExecutionEvent ) + { + ExecutionEvent ee = (ExecutionEvent) arg; + AbstractSession session = ( AbstractSession ) sessionFactory.getSession( ee.getSession() ); + Collection listeners = session.getListeners(); + if ( !listeners.isEmpty() ) + { + Event event = new EventWrapper( session, ee ); + for ( Listener listener : listeners ) + { + listener.onEvent( event ); + } + } + } + } + + @Override + public void close() throws Exception + { + } + + static class MojoExecutionWrapper implements MojoExecution + { + private final org.apache.maven.plugin.MojoExecution delegate; + + MojoExecutionWrapper( org.apache.maven.plugin.MojoExecution delegate ) + { + this.delegate = delegate; + } + + @Override + public Plugin getPlugin() + { + return delegate.getPlugin().getDelegate(); + } + + @Override + public String getExecutionId() + { + return delegate.getExecutionId(); + } + + @Override + public String getGoal() + { + return delegate.getGoal(); + } + } + + static class EventWrapper implements Event + { + private final AbstractSession session; + private final ExecutionEvent delegate; + + EventWrapper( AbstractSession session, ExecutionEvent delegate ) + { + this.session = session; + this.delegate = delegate; + } + + @Override + public EventType getType() + { + return EventType.valueOf( delegate.getType().name() ); + } + + @Override + public Session getSession() + { + return session; + } + + @Override + public Optional getProject() + { + return Optional.ofNullable( delegate.getProject() ).map( session::getProject ); + } + + @Override + public Optional getMojoExecution() + { + return Optional.ofNullable( delegate.getMojoExecution() ).map( MojoExecutionWrapper::new ); + } + + @Override + public Optional getException() + { + return Optional.empty(); + } + } +} From 4b371f3f93909858f1cc39bd87b4cfd4fd15a609 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 23 Aug 2022 17:43:39 +0200 Subject: [PATCH 79/98] Various fixes in the api implementation --- .../java/org/apache/maven/api/Artifact.java | 4 + .../java/org/apache/maven/api/Project.java | 8 + .../java/org/apache/maven/api/Session.java | 15 + .../maven/api/services/ToolchainManager.java | 21 +- .../internal/DefaultBeanConfigurator.java | 47 +- .../EnhancedComponentConfigurator.java | 67 +++ .../EnhancedConfigurationConverter.java | 125 +++++ .../internal/EnhancedConverterLookup.java | 50 ++ .../internal/impl/DefaultArtifactManager.java | 31 ++ .../impl/DefaultDependencyResolver.java | 3 +- .../internal/impl/DefaultMojoExecution.java | 57 +++ .../internal/impl/DefaultProjectManager.java | 95 +++- .../maven/internal/impl/DefaultSession.java | 46 +- .../internal/impl/DefaultSessionFactory.java | 1 + .../impl/DefaultToolchainManager.java | 6 +- .../internal/LifecycleDependencyResolver.java | 62 ++- .../providers/CleanLifecycleProvider.java | 4 +- .../plugin/DefaultBuildPluginManager.java | 2 +- .../PluginParameterExpressionEvaluator.java | 43 +- .../PluginParameterExpressionEvaluatorV4.java | 479 ++++++++++++++++++ .../internal/DefaultMavenPluginManager.java | 17 +- .../DefaultBeanConfiguratorPathTest.java | 140 +++++ .../model/building/DefaultModelBuilder.java | 16 +- 23 files changed, 1238 insertions(+), 101 deletions(-) create mode 100644 maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedComponentConfigurator.java create mode 100644 maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConfigurationConverter.java create mode 100644 maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConverterLookup.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java create mode 100644 maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorV4.java create mode 100644 maven-core/src/test/java/org/apache/maven/configuration/DefaultBeanConfiguratorPathTest.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index 33ee2e2be588..a9103995b8df 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -28,6 +28,10 @@ /** * TODO: split between Coordinates / AttachedArtifact / ResolvedArtifact ? + * Coordinate: version range + * : version + * ResolvedArtifact: version + file + * AttachedArtifact: */ @Experimental @Immutable diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java index 20f1612a4a0f..928f1ca6085d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -26,6 +26,7 @@ import java.util.List; import java.util.Optional; +import org.apache.maven.api.model.Build; import org.apache.maven.api.model.Model; /** @@ -53,6 +54,13 @@ public interface Project @Nonnull Model getModel(); + @Nonnull + default Build getBuild() + { + Build build = getModel().getBuild(); + return build != null ? build : Build.newInstance(); + } + /** * Returns the path to the pom file for this project. * A project is usually read from the file system and this will point to diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index 6778008ebbe3..bf521b8f0f73 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -24,6 +24,7 @@ import org.apache.maven.api.annotations.ThreadSafe; import java.nio.file.Path; +import java.time.Instant; import java.util.Collection; import java.util.List; import java.util.Map; @@ -68,6 +69,20 @@ public interface Session @Nonnull String getMavenVersion(); + int getDegreeOfConcurrency(); + + @Nonnull + Instant getStartTime(); + + @Nonnull + Path getMultiModuleProjectDirectory(); + + @Nonnull + Path getExecutionRootDirectory(); + + @Nonnull + List getProjects(); + /** * Returns the plugin context for mojo being executed and the specified * {@link Project}, never returns {@code null} as if context not present, creates it. diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java index a6f637110923..fc2a4082f50f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java @@ -21,11 +21,13 @@ import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Toolchain; import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; @Experimental public interface ToolchainManager extends Service @@ -37,18 +39,20 @@ public interface ToolchainManager extends Service * @param type * @param requirements * @return the selected {@link Toolchain}s - * @throws ToolchainManagerException if an exceptino occurs + * @throws ToolchainManagerException if an exception occurs */ - List getToolchains( Session session, String type, Map requirements ); + @Nonnull + List getToolchains( @Nonnull Session session, String type, Map requirements ); /** * * @param session * @param type * @return the selected {@link Toolchain} - * @throws ToolchainManagerException if an exceptino occurs + * @throws ToolchainManagerException if an exception occurs */ - Toolchain getToolchainFromBuildContext( Session session, String type ) + @Nonnull + Optional getToolchainFromBuildContext( @Nonnull Session session, String type ) throws ToolchainManagerException; /** @@ -56,17 +60,18 @@ Toolchain getToolchainFromBuildContext( Session session, String type ) * @param session * @param type * @return the selected {@link Toolchain}s - * @throws ToolchainManagerException if an exceptino occurs + * @throws ToolchainManagerException if an exception occurs */ - List getToolchainsForType( Session session, String type ) + @Nonnull + List getToolchainsForType( @Nonnull Session session, String type ) throws ToolchainManagerException; /** * * @param session * @param toolchain - * @throws ToolchainManagerException if an exceptino occurs + * @throws ToolchainManagerException if an exception occurs */ - void storeToolchainToBuildContext( Session session, Toolchain toolchain ) + void storeToolchainToBuildContext( @Nonnull Session session, Toolchain toolchain ) throws ToolchainManagerException; } diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java index ed01875cf5cb..6d170896b8be 100644 --- a/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/DefaultBeanConfigurator.java @@ -20,6 +20,8 @@ */ import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; import java.util.Objects; import javax.inject.Named; @@ -31,10 +33,12 @@ import org.apache.maven.configuration.BeanConfigurationValuePreprocessor; import org.apache.maven.configuration.BeanConfigurator; import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ConfigurationListener; +import org.codehaus.plexus.component.configurator.converters.basic.AbstractBasicConverter; import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; -import org.codehaus.plexus.component.configurator.converters.lookup.DefaultConverterLookup; import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator; import org.codehaus.plexus.configuration.PlexusConfiguration; import org.codehaus.plexus.configuration.xml.XmlPlexusConfiguration; @@ -52,7 +56,12 @@ public class DefaultBeanConfigurator implements BeanConfigurator { - private final ConverterLookup converterLookup = new DefaultConverterLookup(); + private final ConverterLookup converterLookup; + + public DefaultBeanConfigurator() + { + converterLookup = new EnhancedConverterLookup(); + } public void configureBean( BeanConfigurationRequest request ) throws BeanConfigurationException @@ -94,11 +103,12 @@ else if ( configuration instanceof Xpp3Dom ) BeanExpressionEvaluator evaluator = new BeanExpressionEvaluator( request ); - ObjectWithFieldsConverter converter = new ObjectWithFieldsConverter(); + ObjectWithFieldsConverter converter = new EnhancedConfigurationConverter(); try { - converter.processConfiguration( converterLookup, request.getBean(), classLoader, plexusConfig, evaluator ); + converter.processConfiguration( converterLookup, request.getBean(), classLoader, + plexusConfig, evaluator, null ); } catch ( ComponentConfigurationException e ) { @@ -154,4 +164,33 @@ public File alignToBaseDirectory( File file ) } + static class PathConverter extends AbstractBasicConverter + { + @Override + public boolean canConvert( Class type ) + { + return Path.class.equals( type ); + } + + @Override + protected Object fromString( String value ) throws ComponentConfigurationException + { + return Paths.get( value.replace( '/' == File.separatorChar ? '\\' : '/', File.separatorChar ) ); + } + + @Override + public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfiguration configuration, + final Class type, final Class enclosingType, final ClassLoader loader, + final ExpressionEvaluator evaluator, final ConfigurationListener listener ) + throws ComponentConfigurationException + { + final Object result = + super.fromConfiguration( lookup, configuration, type, enclosingType, loader, evaluator, listener ); + + return result instanceof Path + ? evaluator.alignToBaseDirectory( ( (Path) result ).toFile() ).toPath() : result; + } + + } + } diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedComponentConfigurator.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedComponentConfigurator.java new file mode 100644 index 000000000000..defe38bcefb4 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedComponentConfigurator.java @@ -0,0 +1,67 @@ +package org.apache.maven.configuration.internal; + +/* + * 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. + */ + +import javax.inject.Named; +import javax.inject.Singleton; + +import org.codehaus.plexus.classworlds.realm.ClassRealm; +import org.codehaus.plexus.component.configurator.BasicComponentConfigurator; +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ConfigurationListener; +import org.codehaus.plexus.component.configurator.converters.special.ClassRealmConverter; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.configuration.PlexusConfiguration; + +/** + * A component configurator which can leverage the {@link EnhancedConfigurationConverter} + * and {@link EnhancedConverterLookup}. + */ +@Singleton +@Named( "enhanced" ) +public class EnhancedComponentConfigurator + extends BasicComponentConfigurator +{ + + public EnhancedComponentConfigurator() + { + converterLookup = new EnhancedConverterLookup(); + } + + @Override + public void configureComponent( final Object component, final PlexusConfiguration configuration, + final ExpressionEvaluator evaluator, final ClassRealm realm, + final ConfigurationListener listener ) + throws ComponentConfigurationException + { + try + { + ClassRealmConverter.pushContextRealm( realm ); + + new EnhancedConfigurationConverter().processConfiguration( converterLookup, component, realm, // + configuration, evaluator, listener ); + } + finally + { + ClassRealmConverter.popContextRealm(); + } + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConfigurationConverter.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConfigurationConverter.java new file mode 100644 index 000000000000..8bab9a9c1245 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConfigurationConverter.java @@ -0,0 +1,125 @@ +package org.apache.maven.configuration.internal; + +/* + * 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. + */ + +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.ConfigurationListener; +import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; +import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluator; +import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator; +import org.codehaus.plexus.configuration.PlexusConfiguration; +import org.eclipse.sisu.plexus.CompositeBeanHelper; + +/** + * An enhanced {@link ObjectWithFieldsConverter} leveraging the {@link TypeAwareExpressionEvaluator} + * interface. + */ +class EnhancedConfigurationConverter + extends ObjectWithFieldsConverter +{ + protected Object fromExpression( final PlexusConfiguration configuration, final ExpressionEvaluator evaluator, + final Class type ) + throws ComponentConfigurationException + { + String value = configuration.getValue(); + try + { + Object result = null; + if ( null != value && value.length() > 0 ) + { + if ( evaluator instanceof TypeAwareExpressionEvaluator ) + { + result = ( (TypeAwareExpressionEvaluator) evaluator ).evaluate( value, type ); + } + else + { + result = evaluator.evaluate( value ); + } + } + if ( null == result && configuration.getChildCount() == 0 ) + { + value = configuration.getAttribute( "default-value" ); + if ( null != value && value.length() > 0 ) + { + if ( evaluator instanceof TypeAwareExpressionEvaluator ) + { + result = ( (TypeAwareExpressionEvaluator) evaluator ).evaluate( value, type ); + } + else + { + result = evaluator.evaluate( value ); + } + } + } + failIfNotTypeCompatible( result, type, configuration ); + return result; + } + catch ( final ExpressionEvaluationException e ) + { + final String reason = + String.format( "Cannot evaluate expression '%s' for configuration entry '%s'", value, + configuration.getName() ); + + throw new ComponentConfigurationException( configuration, reason, e ); + } + } + + + public Object fromConfiguration( final ConverterLookup lookup, final PlexusConfiguration configuration, + final Class type, final Class enclosingType, final ClassLoader loader, + final ExpressionEvaluator evaluator, final ConfigurationListener listener ) + throws ComponentConfigurationException + { + final Object value = fromExpression( configuration, evaluator, type ); + if ( type.isInstance( value ) ) + { + return value; + } + try + { + final Class implType = getClassForImplementationHint( type, configuration, loader ); + if ( null == value && implType.isInterface() && configuration.getChildCount() == 0 ) + { + return null; // nothing to process + } + final Object bean = instantiateObject( implType ); + if ( null == value ) + { + processConfiguration( lookup, bean, loader, configuration, evaluator, listener ); + } + else + { + new CompositeBeanHelper( lookup, loader, evaluator, listener ) + .setDefault( bean, value, configuration ); + } + return bean; + } + catch ( final ComponentConfigurationException e ) + { + if ( null == e.getFailedConfiguration() ) + { + e.setFailedConfiguration( configuration ); + } + throw e; + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConverterLookup.java b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConverterLookup.java new file mode 100644 index 000000000000..9399cec11788 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/configuration/internal/EnhancedConverterLookup.java @@ -0,0 +1,50 @@ +package org.apache.maven.configuration.internal; + +/* + * 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. + */ + +import org.codehaus.plexus.component.configurator.ComponentConfigurationException; +import org.codehaus.plexus.component.configurator.converters.ConfigurationConverter; +import org.codehaus.plexus.component.configurator.converters.composite.ObjectWithFieldsConverter; +import org.codehaus.plexus.component.configurator.converters.lookup.ConverterLookup; +import org.codehaus.plexus.component.configurator.converters.lookup.DefaultConverterLookup; + +class EnhancedConverterLookup implements ConverterLookup +{ + private final ConverterLookup delegate = new DefaultConverterLookup(); + + EnhancedConverterLookup() + { + registerConverter( new DefaultBeanConfigurator.PathConverter() ); + } + + @Override + public void registerConverter( ConfigurationConverter converter ) + { + delegate.registerConverter( converter ); + } + + @Override + public ConfigurationConverter lookupConverterForType( Class type ) throws ComponentConfigurationException + { + ConfigurationConverter converter = delegate.lookupConverterForType( type ); + return converter.getClass().equals( ObjectWithFieldsConverter.class ) + ? new EnhancedConfigurationConverter() : converter; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java index 54d9eaed37e4..818719701d2f 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java @@ -32,17 +32,36 @@ import org.apache.maven.api.Artifact; import org.apache.maven.api.Metadata; import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.project.MavenProject; public class DefaultArtifactManager implements ArtifactManager { + @Nonnull + private final DefaultSession session; private final Map paths = new ConcurrentHashMap<>(); private final Map> metadatas = new ConcurrentHashMap<>(); + public DefaultArtifactManager( @Nonnull DefaultSession session ) + { + this.session = session; + } + @Nonnull @Override public Optional getPath( @Nonnull Artifact artifact ) { + if ( session.getMavenSession().getAllProjects() != null ) + { + String id = artifact.getId(); + for ( MavenProject project : session.getMavenSession().getAllProjects() ) + { + if ( id.equals( project.getArtifact().getId() ) && project.getArtifact().getFile() != null ) + { + return Optional.of( project.getArtifact().getFile().toPath() ); + } + } + } Path path = paths.get( artifact ); return path != null ? Optional.of( path ) : artifact.getPath(); } @@ -50,6 +69,18 @@ public Optional getPath( @Nonnull Artifact artifact ) @Override public void setPath( @Nonnull Artifact artifact, Path path ) { + if ( session.getMavenSession().getAllProjects() != null ) + { + String id = artifact.getId(); + for ( MavenProject project : session.getMavenSession().getAllProjects() ) + { + if ( id.equals( project.getArtifact().getId() ) ) + { + project.getArtifact().setFile( path != null ? path.toFile() : null ); + break; + } + } + } if ( path == null ) { paths.remove( artifact ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java index e52051218f53..c042608e873c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java @@ -89,7 +89,8 @@ public Node getRoot() @Override public List getArtifactResults() { - return null; + return new MappedList<>( result.getArtifactResults(), + ar -> () -> session.getArtifact( ar.getArtifact() ) ); } }; } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java new file mode 100644 index 000000000000..4080b20cf158 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java @@ -0,0 +1,57 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.MojoExecution; +import org.apache.maven.api.model.Plugin; + +public class DefaultMojoExecution + implements MojoExecution +{ + private final org.apache.maven.plugin.MojoExecution delegate; + + public DefaultMojoExecution( org.apache.maven.plugin.MojoExecution delegate ) + { + this.delegate = delegate; + } + + public org.apache.maven.plugin.MojoExecution getDelegate() + { + return delegate; + } + + @Override + public Plugin getPlugin() + { + return delegate.getPlugin().getDelegate(); + } + + @Override + public String getExecutionId() + { + return delegate.getExecutionId(); + } + + @Override + public String getGoal() + { + return delegate.getGoal(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java index ad2dcec7a47c..0a06ab00e6df 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java @@ -19,13 +19,13 @@ * under the License. */ -import org.apache.maven.api.annotations.Nonnull; - import java.nio.file.Path; +import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; +import java.util.Set; import java.util.stream.Collectors; import org.apache.maven.RepositoryUtils; @@ -33,25 +33,46 @@ import org.apache.maven.api.Node; import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.MavenException; import org.apache.maven.api.services.ProjectManager; import org.apache.maven.api.services.ResolutionScope; +import org.apache.maven.lifecycle.LifecycleExecutionException; +import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; + +import static org.apache.maven.artifact.Artifact.SCOPE_COMPILE; +import static org.apache.maven.artifact.Artifact.SCOPE_PROVIDED; +import static org.apache.maven.artifact.Artifact.SCOPE_RUNTIME; +import static org.apache.maven.artifact.Artifact.SCOPE_SYSTEM; +import static org.apache.maven.artifact.Artifact.SCOPE_TEST; public class DefaultProjectManager implements ProjectManager { + private final Session session; private final ArtifactManager artifactManager; + private final PlexusContainer container; - public DefaultProjectManager( ArtifactManager artifactManager ) + public DefaultProjectManager( Session session, + ArtifactManager artifactManager, + PlexusContainer container ) { + this.session = session; this.artifactManager = artifactManager; + this.container = container; } @Nonnull @Override public Optional getPath( Project project ) { - throw new UnsupportedOperationException(); + // TODO: apiv4 + throw new UnsupportedOperationException( "Not implemented yet" ); } @Nonnull @@ -59,7 +80,7 @@ public Optional getPath( Project project ) public Collection getAttachedArtifacts( Project project ) { AbstractSession session = ( (DefaultProject ) project ).getSession(); - Collection attached = ( ( DefaultProject ) project ).getProject().getAttachedArtifacts().stream() + Collection attached = getMavenProject( project ).getAttachedArtifacts().stream() .map( RepositoryUtils::toArtifact ) .map( session::getArtifact ) .collect( Collectors.toList() ); @@ -69,7 +90,7 @@ public Collection getAttachedArtifacts( Project project ) @Override public void attachArtifact( Project project, Artifact artifact, Path path ) { - ( ( DefaultProject ) project ).getProject().addAttachedArtifact( + getMavenProject( project ).addAttachedArtifact( RepositoryUtils.toArtifact( ( ( DefaultProject ) project ).getSession().toArtifact( artifact ) ) ); artifactManager.setPath( artifact, path ); } @@ -77,46 +98,94 @@ public void attachArtifact( Project project, Artifact artifact, Path path ) @Override public List getCompileSourceRoots( Project project ) { - List roots = ( ( DefaultProject ) project ).getProject().getCompileSourceRoots(); + List roots = getMavenProject( project ).getCompileSourceRoots(); return Collections.unmodifiableList( roots ); } @Override public void addCompileSourceRoot( Project project, String sourceRoot ) { - List roots = ( ( DefaultProject ) project ).getProject().getCompileSourceRoots(); + List roots = getMavenProject( project ).getCompileSourceRoots(); roots.add( sourceRoot ); } @Override public List getTestCompileSourceRoots( Project project ) { - List roots = ( ( DefaultProject ) project ).getProject().getTestCompileSourceRoots(); + List roots = getMavenProject( project ).getTestCompileSourceRoots(); return Collections.unmodifiableList( roots ); } @Override public void addTestCompileSourceRoot( Project project, String sourceRoot ) { - List roots = ( ( DefaultProject ) project ).getProject().getTestCompileSourceRoots(); + List roots = getMavenProject( project ).getTestCompileSourceRoots(); roots.add( sourceRoot ); } @Override public List getRepositories( Project project ) { - return null; + // TODO: apiv4 + throw new UnsupportedOperationException( "Not implemented yet" ); } @Override public List getResolvedDependencies( Project project, ResolutionScope scope ) { - return null; + Collection toResolve = toScopes( scope ); + try + { + LifecycleDependencyResolver lifecycleDependencyResolver = + container.lookup( LifecycleDependencyResolver.class ); + Set artifacts = lifecycleDependencyResolver.resolveProjectArtifacts( + getMavenProject( project ), + toResolve, + toResolve, + ( ( DefaultSession ) session ).getMavenSession(), + false, + Collections.emptySet() + ); + return artifacts.stream() + .map( RepositoryUtils::toArtifact ) + .map( ( ( DefaultSession ) session )::getArtifact ) + .collect( Collectors.toList() ); + } + catch ( LifecycleExecutionException | ComponentLookupException e ) + { + throw new MavenException( "Unable to resolve project dependencies", e ); + } } @Override public Node getCollectedDependencies( Project project, ResolutionScope scope ) { - return null; + // TODO: apiv4 + throw new UnsupportedOperationException( "Not implemented yet" ); + } + + private MavenProject getMavenProject( Project project ) + { + return ( ( DefaultProject ) project ).getProject(); + } + + private Collection toScopes( ResolutionScope scope ) + { + switch ( scope ) + { + case Compile: + return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_PROVIDED ); + case Runtime: + return Arrays.asList( SCOPE_COMPILE, SCOPE_RUNTIME ); + case CompileRuntime: + return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_PROVIDED, SCOPE_RUNTIME ); + case RuntimeSystem: + return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_RUNTIME ); + case Test: + return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_PROVIDED, SCOPE_RUNTIME, SCOPE_TEST ); + default: + throw new IllegalArgumentException(); + } } + } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index 7fd28a0ed890..e05eb0fb20c6 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -19,6 +19,9 @@ * under the License. */ +import java.nio.file.Path; +import java.nio.file.Paths; +import java.time.Instant; import java.util.Collections; import java.util.List; import java.util.Map; @@ -86,8 +89,8 @@ public class DefaultSession extends AbstractSession private final org.apache.maven.project.ProjectBuilder projectBuilder; private final MavenRepositorySystem mavenRepositorySystem; private final DefaultToolchainManagerPrivate toolchainManagerPrivate; - private final ArtifactManager artifactManager = new DefaultArtifactManager(); - private final ProjectManager projectManager = new DefaultProjectManager( artifactManager ); + private final ArtifactManager artifactManager; + private final ProjectManager projectManager; private final PlexusContainer container; private final MojoExecutionScope mojoExecutionScope; private final RuntimeInformation runtimeInformation; @@ -116,9 +119,11 @@ public DefaultSession( @Nonnull MavenSession session, this.container = container; this.mojoExecutionScope = mojoExecutionScope; this.runtimeInformation = runtimeInformation; + this.artifactManager = new DefaultArtifactManager( this ); + this.projectManager = new DefaultProjectManager( this, artifactManager, container ); } - MavenSession getMavenSession() + public MavenSession getMavenSession() { return mavenSession; } @@ -165,6 +170,41 @@ public String getMavenVersion() return runtimeInformation.getMavenVersion(); } + @Override + public int getDegreeOfConcurrency() + { + return mavenSession.getRequest().getDegreeOfConcurrency(); + } + + @Nonnull + @Override + public Instant getStartTime() + { + return mavenSession.getStartTime().toInstant(); + } + + @Nonnull + @Override + public Path getMultiModuleProjectDirectory() + { + return mavenSession.getRequest().getMultiModuleProjectDirectory().toPath(); + } + + @Nonnull + @Override + public Path getExecutionRootDirectory() + { + return Paths.get( mavenSession.getRequest().getBaseDirectory() ); + } + + @Nonnull + @Override + public List getProjects() + { + return getProjects( mavenSession.getProjects() ); + } + + @Nonnull @Override public Map getPluginContext( Project project ) { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java index a7689a56a3d9..d8fab05ef82c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -47,6 +47,7 @@ public class DefaultSessionFactory private final RuntimeInformation runtimeInformation; @Inject + @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultSessionFactory( RepositorySystem repositorySystem, ProjectBuilder projectBuilder, MavenRepositorySystem mavenRepositorySystem, diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java index 6c285cdab5e4..f40de6585581 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultToolchainManager.java @@ -22,6 +22,7 @@ import java.util.Arrays; import java.util.List; import java.util.Map; +import java.util.Optional; import org.apache.maven.api.Session; import org.apache.maven.api.Toolchain; @@ -52,11 +53,12 @@ public List getToolchains( Session session, String type, Map getToolchainFromBuildContext( Session session, String type ) throws ToolchainManagerException { MavenSession s = ( ( DefaultSession ) session ).getMavenSession(); - return toToolchain( toolchainManagerPrivate.getToolchainFromBuildContext( type, s ) ); + return Optional.ofNullable( toolchainManagerPrivate.getToolchainFromBuildContext( type, s ) ) + .map( this::toToolchain ); } @Override diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java index 1eb7bebea3fe..b3b26210f0e5 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/internal/LifecycleDependencyResolver.java @@ -128,32 +128,8 @@ public void resolveProjectDependencies( MavenProject project, Collection } } - Set resolvedArtifacts; - ProjectArtifactsCache.Key cacheKey = projectArtifactsCache.createKey( project, scopesToCollect, - scopesToResolve, aggregating, session.getRepositorySession() ); - ProjectArtifactsCache.CacheRecord recordArtifacts; - recordArtifacts = projectArtifactsCache.get( cacheKey ); - - if ( recordArtifacts != null ) - { - resolvedArtifacts = recordArtifacts.getArtifacts(); - } - else - { - try - { - resolvedArtifacts = getDependencies( project, scopesToCollect, scopesToResolve, session, - aggregating, projectArtifacts ); - recordArtifacts = projectArtifactsCache.put( cacheKey, resolvedArtifacts ); - } - catch ( LifecycleExecutionException e ) - { - projectArtifactsCache.put( cacheKey, e ); - projectArtifactsCache.register( project, cacheKey, recordArtifacts ); - throw e; - } - } - projectArtifactsCache.register( project, cacheKey, recordArtifacts ); + Set resolvedArtifacts = resolveProjectArtifacts( project, scopesToCollect, scopesToResolve, + session, aggregating, projectArtifacts ); Map reactorProjects = new HashMap<>( session.getProjects().size() ); for ( MavenProject reactorProject : session.getProjects() ) @@ -201,6 +177,40 @@ public void resolveProjectDependencies( MavenProject project, Collection } } + public Set resolveProjectArtifacts( MavenProject project, Collection scopesToCollect, + Collection scopesToResolve, MavenSession session, + boolean aggregating, Set projectArtifacts ) + throws LifecycleExecutionException + { + Set resolvedArtifacts; + ProjectArtifactsCache.Key cacheKey = projectArtifactsCache.createKey( project, scopesToCollect, + scopesToResolve, aggregating, session.getRepositorySession() ); + ProjectArtifactsCache.CacheRecord recordArtifacts; + recordArtifacts = projectArtifactsCache.get( cacheKey ); + + if ( recordArtifacts != null ) + { + resolvedArtifacts = recordArtifacts.getArtifacts(); + } + else + { + try + { + resolvedArtifacts = getDependencies( project, scopesToCollect, scopesToResolve, session, + aggregating, projectArtifacts ); + recordArtifacts = projectArtifactsCache.put( cacheKey, resolvedArtifacts ); + } + catch ( LifecycleExecutionException e ) + { + projectArtifactsCache.put( cacheKey, e ); + projectArtifactsCache.register( project, cacheKey, recordArtifacts ); + throw e; + } + } + projectArtifactsCache.register( project, cacheKey, recordArtifacts ); + return resolvedArtifacts; + } + private Set getDependencies( MavenProject project, Collection scopesToCollect, Collection scopesToResolve, MavenSession session, boolean aggregating, Set projectArtifacts ) diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java index db42df1c03c2..740717551e64 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java @@ -40,8 +40,10 @@ public final class CleanLifecycleProvider "post-clean" }; + private static final String MAVEN_CLEAN_PLUGIN_VERSION = "4.0.0-SNAPSHOT"; + private static final String[] BINDINGS = { - "clean", "org.apache.maven.plugins:maven-clean-plugin:3.1.0:clean" + "clean", "org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION + ":clean" }; // END SNIPPET: clean diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index fddda494debc..021a778285c4 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -257,7 +257,7 @@ public void execute() throws MojoExecutionException, MojoFailureException } catch ( MojoException e ) { - throw new MojoExecutionException( e ); + throw new MojoExecutionException( e.getMessage(), e ); } } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java index 656b0a30cb94..acd2ceeb7328 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluator.java @@ -23,7 +23,6 @@ import java.util.Properties; import org.apache.maven.execution.MavenSession; -import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; import org.apache.maven.project.MavenProject; @@ -201,14 +200,7 @@ public Object evaluate( String expr, Class type ) } else if ( "session".equals( expression ) ) { - if ( mojoDescriptor.isV4Api() ) - { - value = session.getSession(); - } - else - { - value = session; - } + value = session; } else if ( expression.startsWith( "session" ) ) { @@ -236,40 +228,15 @@ else if ( expression.startsWith( "session" ) ) } else if ( "reactorProjects".equals( expression ) ) { - if ( mojoDescriptor.isV4Api() ) - { - value = ( ( DefaultSession ) session.getSession() ).getProjects( session.getProjects() ); - } - else - { - value = session.getProjects(); - } - } - else if ( "mojoExecution".equals( expression ) ) - { - value = mojoExecution; + value = session.getProjects(); } else if ( "project".equals( expression ) ) { - if ( mojoDescriptor.isV4Api() ) - { - value = ( (DefaultSession) session.getSession() ).getProject( project ); - } - else - { - value = project; - } + value = project; } else if ( "executedProject".equals( expression ) ) { - if ( mojoDescriptor.isV4Api() ) - { - value = ( (DefaultSession) session.getSession() ).getProject( project.getExecutionProject() ); - } - else - { - value = project.getExecutionProject(); - } + value = project.getExecutionProject(); } else if ( expression.startsWith( "project" ) || expression.startsWith( "pom" ) ) { @@ -299,7 +266,7 @@ else if ( expression.equals( "repositorySystemSession" ) ) { value = session.getRepositorySession(); } - else if ( expression.equals( "mojo" ) ) + else if ( expression.equals( "mojo" ) || expression.equals( "mojoExecution" ) ) { value = mojoExecution; } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorV4.java b/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorV4.java new file mode 100644 index 000000000000..e4756e221d05 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/plugin/PluginParameterExpressionEvaluatorV4.java @@ -0,0 +1,479 @@ +package org.apache.maven.plugin; + +/* + * 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. + */ + +import java.io.File; +import java.nio.file.Path; +import java.nio.file.Paths; +import java.util.Optional; +import java.util.Properties; + +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.internal.impl.DefaultMojoExecution; +import org.apache.maven.internal.impl.DefaultSession; +import org.apache.maven.plugin.descriptor.MojoDescriptor; +import org.apache.maven.plugin.descriptor.PluginDescriptor; +import org.codehaus.plexus.component.configurator.expression.ExpressionEvaluationException; +import org.codehaus.plexus.component.configurator.expression.TypeAwareExpressionEvaluator; +import org.codehaus.plexus.util.introspection.ReflectionValueExtractor; + +/** + * Evaluator for plugin parameters expressions. Content surrounded by ${ and } is evaluated. + * Recognized values are: + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + * + *
Expression matrix
expression evaluation result
session the actual {@link Session}
session.* (since Maven 3)
localRepository {@link Session#getLocalRepository()}
reactorProjects {@link MavenSession#getProjects()}
project {@link Session#getCurrentProject()}
project.*
pom.* (since Maven 3)same as project.*
executedProject {@link MavenProject#getExecutionProject()}
settings {@link Session#getSettings()}
settings.*
basedir {@link Session#getExecutionRootDirectory()} or + * System.getProperty( "user.dir" ) if null
mojoExecution the actual {@link MojoExecution}
mojo (since Maven 3)same as mojoExecution
mojo.* (since Maven 3)
plugin (since Maven 3){@link MojoExecution#getMojoDescriptor()}.{@link MojoDescriptor#getPluginDescriptor() + * getPluginDescriptor()}
plugin.*
* system properties
* project properties
+ * Notice: reports was supported in Maven 2.x but was removed in Maven 3 + * + * @author Jason van Zyl + * @see Session + * @see MojoExecution + */ +public class PluginParameterExpressionEvaluatorV4 + implements TypeAwareExpressionEvaluator +{ + private Session session; + + private MojoExecution mojoExecution; + + private Project project; + + private Path basedir; + + private Properties properties; + + public PluginParameterExpressionEvaluatorV4( Session session, Project project ) + { + this( session, project, null ); + } + + public PluginParameterExpressionEvaluatorV4( Session session, Project project, MojoExecution mojoExecution ) + { + this.session = session; + this.mojoExecution = mojoExecution; + this.properties = new Properties(); + this.project = project; + + // + // Maven4: We may want to evaluate how this is used but we add these separate as the + // getExecutionProperties is deprecated in MavenSession. + // + this.properties.putAll( session.getUserProperties() ); + this.properties.putAll( session.getSystemProperties() ); + + Path basedir = null; + + if ( project != null ) + { + Optional projectFile = project.getBasedir(); + + // this should always be the case for non-super POM instances... + if ( projectFile.isPresent() ) + { + basedir = projectFile.get().toAbsolutePath(); + } + } + + if ( basedir == null ) + { + basedir = session.getExecutionRootDirectory(); + } + + if ( basedir == null ) + { + basedir = Paths.get( System.getProperty( "user.dir" ) ); + } + + this.basedir = basedir; + } + + @Override + public Object evaluate( String expr ) + throws ExpressionEvaluationException + { + return evaluate( expr, null ); + } + + @Override + @SuppressWarnings( "checkstyle:methodlength" ) + public Object evaluate( String expr, Class type ) + throws ExpressionEvaluationException + { + Object value = null; + + if ( expr == null ) + { + return null; + } + + String expression = stripTokens( expr ); + if ( expression.equals( expr ) ) + { + int index = expr.indexOf( "${" ); + if ( index >= 0 ) + { + int lastIndex = expr.indexOf( '}', index ); + if ( lastIndex >= 0 ) + { + String retVal = expr.substring( 0, index ); + + if ( ( index > 0 ) && ( expr.charAt( index - 1 ) == '$' ) ) + { + retVal += expr.substring( index + 1, lastIndex + 1 ); + } + else + { + Object subResult = evaluate( expr.substring( index, lastIndex + 1 ) ); + + if ( subResult != null ) + { + retVal += subResult; + } + else + { + retVal += "$" + expr.substring( index + 1, lastIndex + 1 ); + } + } + + retVal += evaluate( expr.substring( lastIndex + 1 ) ); + return retVal; + } + } + + // Was not an expression + if ( expression.contains( "$$" ) ) + { + return expression.replaceAll( "\\$\\$", "\\$" ); + } + else + { + return expression; + } + } + + if ( "localRepository".equals( expression ) ) + { + // TODO: v4 + value = session.getLocalRepository(); + } + else if ( "session".equals( expression ) ) + { + value = session; + } + else if ( expression.startsWith( "session" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, session ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), session ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( "reactorProjects".equals( expression ) ) + { + value = session.getProjects(); + } + else if ( "project".equals( expression ) ) + { + value = project; + } + else if ( "executedProject".equals( expression ) ) + { + value = ( (DefaultSession) session ).getProject( + ( (DefaultSession) session ).getMavenSession().getCurrentProject().getExecutionProject() ); + } + else if ( expression.startsWith( "project" ) || expression.startsWith( "pom" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 0, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, project ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), project ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( expression.equals( "repositorySystemSession" ) ) + { + // TODO: v4 + } + else if ( expression.equals( "mojo" ) || expression.equals( "mojoExecution" ) ) + { + value = new DefaultMojoExecution( mojoExecution ); + } + else if ( expression.startsWith( "mojo" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, mojoExecution ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), mojoExecution ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( expression.equals( "plugin" ) ) + { + // TODO: v4 + value = mojoExecution.getMojoDescriptor().getPluginDescriptor(); + } + else if ( expression.startsWith( "plugin" ) ) + { + // TODO: v4 + try + { + int pathSeparator = expression.indexOf( '/' ); + + PluginDescriptor pluginDescriptor = mojoExecution.getMojoDescriptor().getPluginDescriptor(); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, pluginDescriptor ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), pluginDescriptor ); + } + } + catch ( Exception e ) + { + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( "settings".equals( expression ) ) + { + value = session.getSettings(); + } + else if ( expression.startsWith( "settings" ) ) + { + try + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + String pathExpression = expression.substring( 1, pathSeparator ); + value = ReflectionValueExtractor.evaluate( pathExpression, session.getSettings() ); + value = value + expression.substring( pathSeparator ); + } + else + { + value = ReflectionValueExtractor.evaluate( expression.substring( 1 ), session.getSettings() ); + } + } + catch ( Exception e ) + { + // TODO don't catch exception + throw new ExpressionEvaluationException( "Error evaluating plugin parameter expression: " + expression, + e ); + } + } + else if ( "basedir".equals( expression ) ) + { + value = basedir.toString(); + } + else if ( expression.startsWith( "basedir" ) ) + { + int pathSeparator = expression.indexOf( '/' ); + + if ( pathSeparator > 0 ) + { + value = basedir.toString() + expression.substring( pathSeparator ); + } + } + + /* + * MNG-4312: We neither have reserved all of the above magic expressions nor is their set fixed/well-known (it + * gets occasionally extended by newer Maven versions). This imposes the risk for existing plugins to + * unintentionally use such a magic expression for an ordinary system property. So here we check whether we + * ended up with a magic value that is not compatible with the type of the configured mojo parameter (a string + * could still be converted by the configurator so we leave those alone). If so, back off to evaluating the + * expression from properties only. + */ + if ( value != null && type != null && !( value instanceof String ) && !isTypeCompatible( type, value ) ) + { + value = null; + } + + if ( value == null ) + { + // The CLI should win for defining properties + + if ( properties != null ) + { + // We will attempt to get nab a system property as a way to specify a + // parameter to a plugins. My particular case here is allowing the surefire + // plugin to run a single test so I want to specify that class on the cli + // as a parameter. + + value = properties.getProperty( expression ); + } + + if ( ( value == null ) && ( ( project != null ) && ( project.getModel().getProperties() != null ) ) ) + { + value = project.getModel().getProperties().getProperty( expression ); + } + + } + + if ( value instanceof String ) + { + // TODO without #, this could just be an evaluate call... + + String val = (String) value; + + int exprStartDelimiter = val.indexOf( "${" ); + + if ( exprStartDelimiter >= 0 ) + { + if ( exprStartDelimiter > 0 ) + { + value = val.substring( 0, exprStartDelimiter ) + evaluate( val.substring( exprStartDelimiter ) ); + } + else + { + value = evaluate( val.substring( exprStartDelimiter ) ); + } + } + } + + return value; + } + + private static boolean isTypeCompatible( Class type, Object value ) + { + if ( type.isInstance( value ) ) + { + return true; + } + // likely Boolean -> boolean, Short -> int etc. conversions, it's not the problem case we try to avoid + return ( ( type.isPrimitive() || type.getName().startsWith( "java.lang." ) ) + && value.getClass().getName().startsWith( "java.lang." ) ); + } + + private String stripTokens( String expr ) + { + if ( expr.startsWith( "${" ) && ( expr.indexOf( '}' ) == expr.length() - 1 ) ) + { + expr = expr.substring( 2, expr.length() - 1 ); + } + return expr; + } + + @Override + public File alignToBaseDirectory( File file ) + { + // TODO Copied from the DefaultInterpolator. We likely want to resurrect the PathTranslator or at least a + // similar component for re-usage + if ( file != null ) + { + if ( file.isAbsolute() ) + { + // path was already absolute, just normalize file separator and we're done + } + else if ( file.getPath().startsWith( File.separator ) ) + { + // drive-relative Windows path, don't align with project directory but with drive root + file = file.getAbsoluteFile(); + } + else + { + // an ordinary relative path, align with project directory + file = basedir.resolve( file.getPath() ).normalize().toAbsolutePath().toFile(); + } + } + return file; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index 1af06219e2dd..fc12b121ded6 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -25,6 +25,7 @@ import org.apache.maven.classrealm.ClassRealmManager; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.scope.internal.MojoExecutionScopeModule; +import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.ContextEnabled; import org.apache.maven.plugin.DebugConfigurationListener; @@ -43,6 +44,7 @@ import org.apache.maven.plugin.PluginManagerException; import org.apache.maven.plugin.PluginParameterException; import org.apache.maven.plugin.PluginParameterExpressionEvaluator; +import org.apache.maven.plugin.PluginParameterExpressionEvaluatorV4; import org.apache.maven.plugin.PluginRealmCache; import org.apache.maven.plugin.PluginResolutionException; import org.apache.maven.plugin.descriptor.MojoDescriptor; @@ -607,7 +609,18 @@ else if ( cause instanceof LinkageError ) pomConfiguration = XmlPlexusConfiguration.toPlexusConfiguration( dom ); } - ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution ); + ExpressionEvaluator expressionEvaluator; + if ( mojoDescriptor.isV4Api() ) + { + expressionEvaluator = new PluginParameterExpressionEvaluatorV4( + session.getSession(), + ( ( DefaultSession ) session.getSession() ).getProject( session.getCurrentProject() ), + mojoExecution ); + } + else + { + expressionEvaluator = new PluginParameterExpressionEvaluator( session, mojoExecution ); + } for ( MavenPluginConfigurationValidator validator: configurationValidators ) { @@ -637,7 +650,7 @@ private void populateMojoExecutionFields( Object mojo, String executionId, MojoD if ( StringUtils.isEmpty( configuratorId ) ) { - configuratorId = "basic"; + configuratorId = "enhanced"; } try diff --git a/maven-core/src/test/java/org/apache/maven/configuration/DefaultBeanConfiguratorPathTest.java b/maven-core/src/test/java/org/apache/maven/configuration/DefaultBeanConfiguratorPathTest.java new file mode 100644 index 000000000000..c7cf0884b127 --- /dev/null +++ b/maven-core/src/test/java/org/apache/maven/configuration/DefaultBeanConfiguratorPathTest.java @@ -0,0 +1,140 @@ +package org.apache.maven.configuration; + +/* + * 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. + */ + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.nio.file.Path; +import java.nio.file.Paths; + +import org.apache.maven.configuration.internal.DefaultBeanConfigurator; +import org.apache.maven.configuration.internal.EnhancedComponentConfigurator; +import org.codehaus.plexus.util.xml.Xpp3Dom; +import org.codehaus.plexus.util.xml.Xpp3DomBuilder; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.junit.jupiter.api.AfterEach; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import static org.junit.jupiter.api.Assertions.assertEquals; + +/** + * @author Benjamin Bentmann + */ +public class DefaultBeanConfiguratorPathTest +{ + + private BeanConfigurator configurator; + + @BeforeEach + public void setUp() + throws Exception + { + configurator = new DefaultBeanConfigurator(); + } + + @AfterEach + public void tearDown() + throws Exception + { + configurator = null; + } + + private Xpp3Dom toConfig( String xml ) + { + try + { + return Xpp3DomBuilder.build( new StringReader( "" + xml + "" ) ); + } + catch ( XmlPullParserException | IOException e ) + { + throw new IllegalArgumentException( e ); + } + } + + @Test + public void testMinimal() + throws BeanConfigurationException + { + SomeBean bean = new SomeBean(); + + Xpp3Dom config = toConfig( "test" ); + + DefaultBeanConfigurationRequest request = new DefaultBeanConfigurationRequest(); + request.setBean( bean ).setConfiguration( config ); + + configurator.configureBean( request ); + + assertEquals( Paths.get( "test" ), bean.file ); + } + + @Test + public void testPreAndPostProcessing() + throws BeanConfigurationException + { + SomeBean bean = new SomeBean(); + + Xpp3Dom config = toConfig( "${test}" ); + + BeanConfigurationValuePreprocessor preprocessor = ( value, type ) -> + { + if ( value != null && value.startsWith( "${" ) && value.endsWith( "}" ) ) + { + return value.substring( 2, value.length() - 1 ); + } + return value; + }; + + BeanConfigurationPathTranslator translator = path -> new File( "base", path.getPath() ).getAbsoluteFile(); + + DefaultBeanConfigurationRequest request = new DefaultBeanConfigurationRequest(); + request.setBean( bean ).setConfiguration( config ); + request.setValuePreprocessor( preprocessor ).setPathTranslator( translator ); + + configurator.configureBean( request ); + + assertEquals( Paths.get( "base/test" ).toAbsolutePath(), bean.file ); + } + + @Test + public void testChildConfigurationElement() + throws BeanConfigurationException + { + SomeBean bean = new SomeBean(); + + Xpp3Dom config = toConfig( "test" ); + + DefaultBeanConfigurationRequest request = new DefaultBeanConfigurationRequest(); + request.setBean( bean ).setConfiguration( config, "wrapper" ); + + configurator.configureBean( request ); + + assertEquals( Paths.get( "test" ), bean.file ); + } + + static class SomeBean + { + + Path file; + + } + +} diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index 89c5e9b5f032..bd5891a93a83 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1863,7 +1863,14 @@ private Model findRawModel( String groupId, String artifactId ) { ModelBuildingRequest gaBuildingRequest = new DefaultModelBuildingRequest( request ) .setModelSource( (ModelSource) source ); - return readRawModel( gaBuildingRequest, problems ); + Model model = readRawModel( gaBuildingRequest, problems ); + if ( source instanceof FileModelSource ) + { + Path path = ( ( FileModelSource ) source ).getFile().toPath(); + context.modelByPath.computeIfAbsent( path, k -> new DefaultTransformerContext.Holder() ) + .computeIfAbsent( () -> model ); + } + return model; } catch ( ModelBuildingException e ) { @@ -1886,7 +1893,12 @@ private Model findRawModel( Path p ) try { - return readRawModel( req, problems ); + Model model = readRawModel( req, problems ); + DefaultTransformerContext.GAKey key = + new DefaultTransformerContext.GAKey( model.getGroupId(), model.getArtifactId() ); + context.modelByGA.computeIfAbsent( key, k -> new DefaultTransformerContext.Holder() ) + .computeIfAbsent( () -> model ); + return model; } catch ( ModelBuildingException e ) { From bf4995e7f4c8ae473b441539824bf3712f82a553 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Wed, 24 Aug 2022 14:38:46 +0200 Subject: [PATCH 80/98] Add a mojo logging api --- .../java/org/apache/maven/api/plugin/Log.java | 166 ++++++++++++++ .../internal/MojoExecutionScopeModule.java | 2 + .../maven/internal/impl/DefaultLog.java | 210 ++++++++++++++++++ .../plugin/DefaultBuildPluginManager.java | 4 + 4 files changed, 382 insertions(+) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLog.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java new file mode 100644 index 000000000000..09d74b32ac75 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java @@ -0,0 +1,166 @@ +package org.apache.maven.api.plugin; + +/* + * 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. + */ + +import java.util.function.Supplier; + +/** + * This interface supplies the API for providing feedback to the user from the Mojo, using standard + * Maven channels.
+ * There should be no big surprises here, although you may notice that the methods accept + * java.lang.CharSequence rather than java.lang.String. This is provided mainly as a + * convenience, to enable developers to pass things like java.lang.StringBuffer directly into the logger, + * rather than formatting first by calling toString(). + */ +public interface Log +{ + /** + * @return true if the debug error level is enabled + */ + boolean isDebugEnabled(); + + /** + * Send a message to the user in the debug error level. + * + * @param content + */ + void debug( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the debug error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void debug( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the debug error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void debug( Throwable error ); + + void debug( Supplier content ); + + void debug( Supplier content, Throwable error ); + + /** + * @return true if the info error level is enabled + */ + boolean isInfoEnabled(); + + /** + * Send a message to the user in the info error level. + * + * @param content + */ + void info( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the info error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void info( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the info error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void info( Throwable error ); + + void info( Supplier content ); + + void info( Supplier content, Throwable error ); + + /** + * @return true if the warn error level is enabled + */ + boolean isWarnEnabled(); + + /** + * Send a message to the user in the warn error level. + * + * @param content + */ + void warn( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the warn error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void warn( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the warn error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void warn( Throwable error ); + + void warn( Supplier content ); + + void warn( Supplier content, Throwable error ); + + /** + * @return true if the error error level is enabled + */ + boolean isErrorEnabled(); + + /** + * Send a message to the user in the error error level. + * + * @param content + */ + void error( CharSequence content ); + + /** + * Send a message (and accompanying exception) to the user in the error error level.
+ * The error's stacktrace will be output when this error level is enabled. + * + * @param content + * @param error + */ + void error( CharSequence content, Throwable error ); + + /** + * Send an exception to the user in the error error level.
+ * The stack trace for this exception will be output when this error level is enabled. + * + * @param error + */ + void error( Throwable error ); + + void error( Supplier content ); + + void error( Supplier content, Throwable error ); + +} diff --git a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java index 9b2617fe5d87..adad347a8208 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java +++ b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.plugin.Log; import org.apache.maven.execution.scope.MojoExecutionScoped; import org.apache.maven.plugin.MojoExecution; import org.apache.maven.project.MavenProject; @@ -54,6 +55,7 @@ protected void configure() bind( MavenProject.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); bind( MojoExecution.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); + bind( Log.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLog.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLog.java new file mode 100644 index 000000000000..0f044609199a --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLog.java @@ -0,0 +1,210 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.function.Supplier; + +import org.apache.maven.api.plugin.Log; +import org.slf4j.Logger; + +import static java.util.Objects.requireNonNull; + +public class DefaultLog implements Log +{ + private final Logger logger; + + public DefaultLog( Logger logger ) + { + this.logger = requireNonNull( logger ); + } + + public void debug( CharSequence content ) + { + logger.debug( toString( content ) ); + } + + @Override + public void debug( CharSequence content, Throwable error ) + { + logger.debug( toString( content ), error ); + } + + @Override + public void debug( Throwable error ) + { + logger.debug( "", error ); + } + + @Override + public void debug( Supplier content ) + { + if ( isDebugEnabled() ) + { + logger.debug( content.get() ); + } + } + + @Override + public void debug( Supplier content, Throwable error ) + { + if ( isDebugEnabled() ) + { + logger.debug( content.get(), error ); + } + } + + @Override + public void info( CharSequence content ) + { + logger.info( toString( content ) ); + } + + @Override + public void info( CharSequence content, Throwable error ) + { + logger.info( toString( content ), error ); + } + + @Override + public void info( Throwable error ) + { + logger.info( "", error ); + } + + @Override + public void info( Supplier content ) + { + if ( isInfoEnabled() ) + { + logger.info( content.get() ); + } + } + + @Override + public void info( Supplier content, Throwable error ) + { + if ( isInfoEnabled() ) + { + logger.info( content.get(), error ); + } + } + + @Override + public void warn( CharSequence content ) + { + logger.warn( toString( content ) ); + } + + @Override + public void warn( CharSequence content, Throwable error ) + { + logger.warn( toString( content ), error ); + } + + @Override + public void warn( Throwable error ) + { + logger.warn( "", error ); + } + + @Override + public void warn( Supplier content ) + { + if ( isWarnEnabled() ) + { + logger.warn( content.get() ); + } + } + + @Override + public void warn( Supplier content, Throwable error ) + { + if ( isWarnEnabled() ) + { + logger.info( content.get(), error ); + } + } + + @Override + public void error( CharSequence content ) + { + logger.error( toString( content ) ); + } + + @Override + public void error( CharSequence content, Throwable error ) + { + logger.error( toString( content ), error ); + } + + @Override + public void error( Throwable error ) + { + logger.error( "", error ); + } + + @Override + public void error( Supplier content ) + { + if ( isErrorEnabled() ) + { + logger.error( content.get() ); + } + } + + @Override + public void error( Supplier content, Throwable error ) + { + if ( isErrorEnabled() ) + { + logger.error( content.get(), error ); + } + } + + @Override + public boolean isDebugEnabled() + { + return logger.isDebugEnabled(); + } + + @Override + public boolean isInfoEnabled() + { + return logger.isInfoEnabled(); + } + + @Override + public boolean isWarnEnabled() + { + return logger.isWarnEnabled(); + } + + @Override + public boolean isErrorEnabled() + { + return logger.isErrorEnabled(); + } + + private String toString( CharSequence content ) + { + return content != null ? content.toString() : ""; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index 021a778285c4..828f5377267b 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -32,6 +32,7 @@ import org.apache.maven.execution.MojoExecutionEvent; import org.apache.maven.execution.MojoExecutionListener; import org.apache.maven.execution.scope.internal.MojoExecutionScope; +import org.apache.maven.internal.impl.DefaultLog; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; @@ -40,6 +41,7 @@ import org.codehaus.plexus.classworlds.realm.ClassRealm; import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.repository.RemoteRepository; +import org.slf4j.LoggerFactory; // TODO the antrun plugin has its own configurator, the only plugin that does. might need to think about how that works // TODO remove the coreArtifactFilterManager @@ -122,6 +124,8 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) { scope.seed( MavenProject.class, project ); scope.seed( MojoExecution.class, mojoExecution ); + scope.seed( org.apache.maven.api.plugin.Log.class, new DefaultLog( + LoggerFactory.getLogger( mojoExecution.getMojoDescriptor().getFullGoalName() ) ) ); if ( mojoDescriptor.isV4Api() ) { From 38c6397c1768e39047751cab62ab41b89078a219 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 2 Sep 2022 11:22:55 +0200 Subject: [PATCH 81/98] Fix remaining ITs --- .../maven/lifecycle/providers/CleanLifecycleProvider.java | 2 +- .../apache/maven/plugin/internal/DefaultMavenPluginManager.java | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java index 740717551e64..4ffbdbbb439f 100644 --- a/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java +++ b/maven-core/src/main/java/org/apache/maven/lifecycle/providers/CleanLifecycleProvider.java @@ -40,7 +40,7 @@ public final class CleanLifecycleProvider "post-clean" }; - private static final String MAVEN_CLEAN_PLUGIN_VERSION = "4.0.0-SNAPSHOT"; + private static final String MAVEN_CLEAN_PLUGIN_VERSION = "3.1.0"; private static final String[] BINDINGS = { "clean", "org.apache.maven.plugins:maven-clean-plugin:" + MAVEN_CLEAN_PLUGIN_VERSION + ":clean" diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index fc12b121ded6..a14f891059d2 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -650,7 +650,7 @@ private void populateMojoExecutionFields( Object mojo, String executionId, MojoD if ( StringUtils.isEmpty( configuratorId ) ) { - configuratorId = "enhanced"; + configuratorId = "basic"; } try From 9e46bab9ca5eb0577e3338ea860e4acbf949be79 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 16 Sep 2022 08:48:22 +0200 Subject: [PATCH 82/98] Fix plexus-utils classes in IDE --- maven-xml-impl/pom.xml | 2 +- plexus-utils/pom.xml | 65 +++++++++++++++++++++++++++++++++++++++--- pom.xml | 1 + 3 files changed, 63 insertions(+), 5 deletions(-) diff --git a/maven-xml-impl/pom.xml b/maven-xml-impl/pom.xml index 668176b38834..37933fabf395 100644 --- a/maven-xml-impl/pom.xml +++ b/maven-xml-impl/pom.xml @@ -46,7 +46,7 @@ under the License. org.codehaus.plexus plexus-utils - 3.4.2 + ${plexusUtilsVersionEmbedded} provided diff --git a/plexus-utils/pom.xml b/plexus-utils/pom.xml index 13a0d994e86e..2fc0a1ac3b5a 100644 --- a/plexus-utils/pom.xml +++ b/plexus-utils/pom.xml @@ -37,7 +37,7 @@ under the License. org.codehaus.plexus plexus-utils - 3.4.2 + ${plexusUtilsVersionEmbedded} org.apache.maven @@ -55,8 +55,8 @@ under the License. 3.1.1 - unpack - compile + unpack-sourcs + generate-sources unpack @@ -65,7 +65,32 @@ under the License. org.codehaus.plexus plexus-utils - 3.4.2 + ${plexusUtilsVersionEmbedded} + sources + jar + false + ${project.build.directory}/generated-sources + **/*.java + + org/codehaus/plexus/util/xml/Xpp3Dom.java, + org/codehaus/plexus/util/xml/Xpp3DomBuilder.java + + + + + + + unpack-classes + process-classes + + unpack + + + + + org.codehaus.plexus + plexus-utils + ${plexusUtilsVersionEmbedded} jar false ${project.build.directory}/classes @@ -99,6 +124,38 @@ under the License.
+ + org.codehaus.mojo + build-helper-maven-plugin + 3.3.0 + + + add-source + generate-sources + + add-source + + + + target/generated-sources + + + + + + + org.apache.maven.plugins + maven-compiler-plugin + 3.10.1 + + + compile + + true + + + + org.codehaus.mojo animal-sniffer-maven-plugin diff --git a/pom.xml b/pom.xml index 86a9d41009ca..950f3f903400 100644 --- a/pom.xml +++ b/pom.xml @@ -56,6 +56,7 @@ under the License. 2.1.0 1.26 4.0.0-alpha-1-SNAPSHOT + 3.4.2 5.1.0 30.1-jre 1.0.1 From 5ccb24df946cd78d6c0a4df630de99700b773d02 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 16 Sep 2022 10:49:00 +0200 Subject: [PATCH 83/98] Restore MavenResolver compatibility by using default methods --- .../maven/model/resolution/ModelResolver.java | 40 +++++++++++++++---- 1 file changed, 32 insertions(+), 8 deletions(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java index 0812f0ed15b0..b3139c58c51d 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/resolution/ModelResolver.java @@ -124,15 +124,39 @@ void addRepository( org.apache.maven.model.Repository repository, boolean replac */ ModelResolver newCopy(); - ModelSource resolveModel( Parent parent, AtomicReference modified ) - throws UnresolvableModelException; + default ModelSource resolveModel( Parent parent, AtomicReference modified ) + throws UnresolvableModelException + { + org.apache.maven.model.Parent p = new org.apache.maven.model.Parent( parent ); + ModelSource result = resolveModel( p ); + if ( p.getDelegate() != parent ) + { + modified.set( p.getDelegate() ); + } + return result; + } - ModelSource resolveModel( Dependency dependency, AtomicReference modified ) - throws UnresolvableModelException; + default ModelSource resolveModel( Dependency dependency, AtomicReference modified ) + throws UnresolvableModelException + { + org.apache.maven.model.Dependency d = new org.apache.maven.model.Dependency( dependency ); + ModelSource result = resolveModel( d ); + if ( d.getDelegate() != dependency ) + { + modified.set( d.getDelegate() ); + } + return result; + } - void addRepository( Repository repository ) - throws InvalidRepositoryException; + default void addRepository( Repository repository ) + throws InvalidRepositoryException + { + addRepository( new org.apache.maven.model.Repository( repository ) ); + } - void addRepository( Repository repository, boolean replace ) - throws InvalidRepositoryException; + default void addRepository( Repository repository, boolean replace ) + throws InvalidRepositoryException + { + addRepository( new org.apache.maven.model.Repository( repository ), replace ); + } } From 03f9517a38a03462cbe181f502ff32f0d9741bc6 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 16 Sep 2022 10:58:45 +0200 Subject: [PATCH 84/98] The raw model may not have a groupId which defaults to the parent's groupId --- .../org/apache/maven/model/building/DefaultModelBuilder.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java index bd5891a93a83..3e21fc72e735 100644 --- a/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java +++ b/maven-model-builder/src/main/java/org/apache/maven/model/building/DefaultModelBuilder.java @@ -1895,7 +1895,7 @@ private Model findRawModel( Path p ) { Model model = readRawModel( req, problems ); DefaultTransformerContext.GAKey key = - new DefaultTransformerContext.GAKey( model.getGroupId(), model.getArtifactId() ); + new DefaultTransformerContext.GAKey( getGroupId( model ), model.getArtifactId() ); context.modelByGA.computeIfAbsent( key, k -> new DefaultTransformerContext.Holder() ) .computeIfAbsent( () -> model ); return model; From 8118bfa92aa1605f43ff8c4ea3ed5623337e16bb Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Tue, 20 Sep 2022 15:30:15 +0200 Subject: [PATCH 85/98] Minor improvements --- .../java/org/apache/maven/api/Artifact.java | 2 ++ .../java/org/apache/maven/api/Dependency.java | 4 +++ .../main/java/org/apache/maven/api/Event.java | 2 ++ .../java/org/apache/maven/api/EventType.java | 2 ++ .../java/org/apache/maven/api/Exclusion.java | 6 ++++ .../org/apache/maven/api/JavaToolchain.java | 5 ++++ .../java/org/apache/maven/api/Listener.java | 2 ++ .../org/apache/maven/api/LocalRepository.java | 8 +++++ .../java/org/apache/maven/api/Metadata.java | 2 ++ .../org/apache/maven/api/MetadataStorage.java | 2 ++ .../org/apache/maven/api/MojoExecution.java | 3 ++ .../main/java/org/apache/maven/api/Node.java | 10 ++++++- .../org/apache/maven/api/NodeVisitor.java | 3 +- .../java/org/apache/maven/api/Project.java | 3 ++ .../apache/maven/api/RemoteRepository.java | 5 ++++ .../java/org/apache/maven/api/Repository.java | 9 ++++++ .../apache/maven/api/RepositoryMetadata.java | 4 +++ .../java/org/apache/maven/api/Service.java | 2 +- .../java/org/apache/maven/api/Session.java | 2 ++ .../org/apache/maven/api/SessionData.java | 1 + .../java/org/apache/maven/api/Toolchain.java | 2 ++ .../java/org/apache/maven/api/Version.java | 6 +++- .../org/apache/maven/api/VersionRange.java | 2 ++ .../java/org/apache/maven/api/plugin/Log.java | 2 ++ .../maven/api/plugin/MojoException.java | 3 +- .../maven/api/services/ArtifactDeployer.java | 5 +++- .../services/ArtifactDeployerException.java | 3 +- .../api/services/ArtifactDeployerRequest.java | 4 +++ .../maven/api/services/ArtifactFactory.java | 2 ++ .../api/services/ArtifactFactoryRequest.java | 5 ++++ .../maven/api/services/ArtifactInstaller.java | 5 +++- .../services/ArtifactInstallerException.java | 2 +- .../services/ArtifactInstallerRequest.java | 2 ++ .../maven/api/services/ArtifactManager.java | 4 +++ .../maven/api/services/ArtifactResolver.java | 2 ++ .../services/ArtifactResolverException.java | 4 ++- .../api/services/ArtifactResolverRequest.java | 2 ++ .../api/services/ArtifactResolverResult.java | 3 +- .../maven/api/services/BaseRequest.java | 2 ++ .../api/services/DependencyCollector.java | 3 +- .../DependencyCollectorException.java | 6 ++-- .../services/DependencyCollectorRequest.java | 1 + .../services/DependencyCollectorResult.java | 1 + .../maven/api/services/DependencyFactory.java | 4 +++ .../services/DependencyFactoryRequest.java | 4 +++ .../api/services/DependencyResolver.java | 3 +- .../services/DependencyResolverException.java | 2 ++ .../services/DependencyResolverRequest.java | 2 ++ .../services/DependencyResolverResult.java | 3 +- .../api/services/LocalRepositoryManager.java | 4 +++ .../maven/api/services/MavenException.java | 9 +++--- .../maven/api/services/MessageBuilder.java | 2 ++ .../api/services/MessageBuilderFactory.java | 2 ++ .../maven/api/services/ProjectBuilder.java | 3 ++ .../api/services/ProjectBuilderException.java | 4 ++- .../api/services/ProjectBuilderProblem.java | 8 ++--- .../ProjectBuilderProblemSeverity.java | 2 ++ .../api/services/ProjectBuilderRequest.java | 6 ++++ .../api/services/ProjectBuilderResult.java | 5 ++++ .../api/services/ProjectBuilderSource.java | 5 ++++ .../maven/api/services/ProjectManager.java | 4 ++- .../apache/maven/api/services/Prompter.java | 5 ++++ .../maven/api/services/PrompterException.java | 4 ++- .../maven/api/services/RepositoryFactory.java | 5 ++++ .../maven/api/services/ResolutionScope.java | 2 ++ .../maven/api/services/ToolchainFactory.java | 3 ++ .../maven/api/services/ToolchainManager.java | 5 ++++ .../services/ToolchainManagerException.java | 4 ++- .../maven/api/services/VersionParser.java | 5 +++- .../api/services/VersionParserException.java | 4 ++- .../api/services/xml/ModelXmlFactory.java | 5 ++++ .../api/services/xml/SettingsXmlFactory.java | 5 ++++ .../services/xml/ToolchainsXmlFactory.java | 5 ++++ .../maven/api/services/xml/XmlFactory.java | 24 +++++++++++++++ .../api/services/xml/XmlReaderException.java | 4 ++- .../api/services/xml/XmlReaderRequest.java | 5 ++++ .../api/services/xml/XmlWriterException.java | 4 ++- .../api/services/xml/XmlWriterRequest.java | 28 +++++++++++++++-- .../maven/api/annotations/Consumer.java | 9 ++++-- .../maven/api/annotations/Experimental.java | 3 ++ .../maven/api/annotations/Generated.java | 9 ++++++ .../maven/api/annotations/Immutable.java | 12 ++++++++ .../apache/maven/api/annotations/Nonnull.java | 7 +++++ .../maven/api/annotations/NotThreadSafe.java | 11 +++++++ .../maven/api/annotations/Nullable.java | 7 +++++ .../maven/api/annotations/Provider.java | 9 ++++-- .../maven/api/annotations/ThreadSafe.java | 12 ++++++++ .../maven/api/annotations/package-info.java | 30 +++++++++++++++++++ .../java/org/apache/maven/api/xml/Dom.java | 7 ++++- .../plugin/velocity/VelocityGenerator.java | 3 -- .../internal/impl/DefaultModelXmlFactory.java | 15 ++++++++-- plexus-utils/pom.xml | 4 +-- 92 files changed, 422 insertions(+), 53 deletions(-) create mode 100644 api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/package-info.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index a9103995b8df..efd15df28aeb 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -32,6 +32,8 @@ * : version * ResolvedArtifact: version + file * AttachedArtifact: + * + * @since 4.0 */ @Experimental @Immutable diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java index 33603a41f380..8e25584708ec 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -26,6 +26,10 @@ import java.util.Collection; +/** + * + * @since 4.0 + */ @Experimental @Immutable public interface Dependency diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java index f22f3d4cfbe4..0a30dba8fd51 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Event.java @@ -28,6 +28,8 @@ * Event sent by maven during various phases of the build process. * Such events can be listened to using {@link Listener}s objects * registered in the {@link Session}. + * + * @since 4.0 */ @Experimental public interface Event diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java index fd4e233b0e55..ad81a2af5da8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java @@ -27,6 +27,8 @@ * TODO: those values are lower cased, while other events are upper-case * we need to align on one strategy * see also {@link MetadataStorage} and {@link org.apache.maven.api.services.ResolutionScope} + * + * @since 4.0 */ @Experimental public enum EventType diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java index 5786196a88eb..472edb8533ef 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java @@ -22,6 +22,12 @@ import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nullable; +/** + * A dependency exlusion. + * + * @since 4.0 + * @see Dependency#getExclusions() + */ @Experimental public interface Exclusion { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java index b97014bcbd3f..21eefa49013f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/JavaToolchain.java @@ -21,6 +21,11 @@ import org.apache.maven.api.annotations.Experimental; +/** + * A specific {@link Toolchain} dedicated for Java. + * + * @since 4.0 + */ @Experimental public interface JavaToolchain extends Toolchain { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java index b71801e5b426..924ddaeaa6ed 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Listener.java @@ -25,6 +25,8 @@ /** * A listener for session events. + * + * @since 4.0 */ @Experimental @FunctionalInterface @Consumer diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java index 4744dc8f25af..4d1101f7613d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/LocalRepository.java @@ -22,9 +22,17 @@ import java.nio.file.Path; import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; +/** + * The local repository is used to cache artifacts downloaded from {@link RemoteRepository} + * and to hold artifacts that have been build locally. + * + * @since 4.0 + */ @Experimental +@Immutable public interface LocalRepository extends Repository { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java index af1eebcf6402..d86aef64809c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Metadata.java @@ -23,6 +23,8 @@ /** * TODO: investigate removing the Metadata api completely + * + * @since 4.0 */ @Experimental public interface Metadata diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java index d7596ccee194..1b988cfc7c5e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MetadataStorage.java @@ -23,6 +23,8 @@ /** * Storage location for metadata + * + * @since 4.0 */ @Experimental public enum MetadataStorage diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java index 053a1e98b7aa..945e59185f63 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java @@ -24,6 +24,9 @@ import org.apache.maven.api.model.Plugin; +/** + * A {@code MojoExecution} + */ @Experimental public interface MojoExecution { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java index 9ce266c56a5f..f79bf943bc90 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java @@ -21,6 +21,7 @@ import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; import java.util.List; import java.util.Optional; @@ -29,6 +30,9 @@ /** * Represents a dependency node within a Maven project's dependency collector. + * + * @since 4.0 + * @see org.apache.maven.api.services.DependencyCollectorResult#getRoot() */ @Experimental @Immutable @@ -49,16 +53,19 @@ public interface Node * * @return the child nodes of this node, never {@code null} */ + @Nonnull List getChildren(); /** * @return repositories of this node */ + @Nonnull List getRemoteRepositories(); /** * The repository where this artifact has been downloaded from. */ + @Nonnull Optional getRepository(); /** @@ -67,7 +74,7 @@ public interface Node * @param visitor The visitor to call back, must not be {@code null}. * @return {@code true} to visit siblings nodes of this node as well, {@code false} to skip siblings. */ - boolean accept( NodeVisitor visitor ); + boolean accept( @Nonnull NodeVisitor visitor ); /** * Returns a new tree starting at this node, filtering the children. @@ -84,6 +91,7 @@ public interface Node * * @return a stream containing this node and its descendant */ + @Nonnull default Stream stream() { return Stream.concat( Stream.of( this ), getChildren().stream().flatMap( Node::stream ) ); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java index 99ffe308c29b..39ae803eacdc 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/NodeVisitor.java @@ -27,8 +27,7 @@ /** * Defines a hierarchical visitor for collecting dependency node trees. * - * @author Pim Moerenhout - * @since 0.12 + * @since 4.0 */ @Experimental @Consumer diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java index 928f1ca6085d..c2483080180c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -31,6 +31,9 @@ /** * Interface representing a Maven project. + * Projects can be built using the {@link org.apache.maven.api.services.ProjectBuilder} service. + * + * @since 4.0 */ @Experimental public interface Project diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java index 7482d07b4514..4dd629f2c59f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RemoteRepository.java @@ -20,9 +20,14 @@ */ import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; +/** + * A remote repository that can be used to download or upload artifacts. + */ @Experimental +@Immutable public interface RemoteRepository extends Repository { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java index abccc7165f8c..10551d737c5d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Repository.java @@ -20,9 +20,18 @@ */ import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; +/** + * A repository holds artifacts. + * + * @since 4.0 + * @see RemoteRepository + * @see LocalRepository + */ @Experimental +@Immutable public interface Repository { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java index 2a8e50ac47df..a64879658bc8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/RepositoryMetadata.java @@ -21,6 +21,10 @@ import org.apache.maven.api.annotations.Experimental; +/** + * + * @since 4.0 + */ @Experimental public interface RepositoryMetadata extends Metadata { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java index afdbb4f2a41a..a4cabcaa7b50 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Service.java @@ -24,7 +24,7 @@ /** * Marker interface for all services provided by the {@link Session}. - * + *

* Services can be retrieved from the session using the * {@link Session#getService(Class)} method. * diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index bf521b8f0f73..a16710af1514 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -38,6 +38,8 @@ /** * The session to install / deploy / resolve artifacts and dependencies. + * + * @since 4.0 */ @Experimental @ThreadSafe diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java index 9b0b0ed64323..8a8ef19401f0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/SessionData.java @@ -37,6 +37,7 @@ * Note: Actual implementations must be thread-safe. * * @see Session#getData() + * @since 4.0 */ @Experimental @ThreadSafe @Provider diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java index 04077850e792..2f497194e33d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Toolchain.java @@ -25,6 +25,8 @@ /** * Toolchain interface. + * + * @since 4.0 */ @Experimental public interface Toolchain diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java index ea409309c7be..6c5371a3e865 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java @@ -23,7 +23,11 @@ import org.apache.maven.api.annotations.Nonnull; /** - * A version. + * A version usually parsed using the {@link org.apache.maven.api.services.VersionParser} service. + * + * @since 4.0 + * @see org.apache.maven.api.services.VersionParser#parseVersion(String) + * @see org.apache.maven.api.Session#parseVersion(String) */ @Experimental public interface Version diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java index 83a730f840e3..398aab3d30b7 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java @@ -24,6 +24,8 @@ /** * A range of versions. + * + * @since 4.0 */ @Experimental public interface VersionRange diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java index 09d74b32ac75..f0eb2a660aaa 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/Log.java @@ -28,6 +28,8 @@ * java.lang.CharSequence rather than java.lang.String. This is provided mainly as a * convenience, to enable developers to pass things like java.lang.StringBuffer directly into the logger, * rather than formatting first by calling toString(). + * + * @since 4.0 */ public interface Log { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java index 81daca08bb8d..5e5b0c7eee1c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/MojoException.java @@ -23,7 +23,8 @@ import org.apache.maven.api.services.MavenException; /** - * An exception occurring during the execution of a plugin.
+ * An exception occurring during the execution of a plugin. + * * @since 4.0 */ @Experimental diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java index d835a274aa65..38c243dbea95 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployer.java @@ -29,7 +29,10 @@ import org.apache.maven.api.annotations.Nonnull; /** - * + * Deploys {@link Artifact}s to a {@link RemoteRepository}. + * + * @since 4.0 + * @see Session#deployArtifact(RemoteRepository, Artifact...) */ @Experimental public interface ArtifactDeployer extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java index 19083d43dd89..fbb206a53489 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerException.java @@ -23,7 +23,8 @@ /** * An artifact could not correctly being deployed. - * + * + * @since 4.0 */ @Experimental public class ArtifactDeployerException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java index 162d0a55a167..a87c0fbfc957 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactDeployerRequest.java @@ -20,6 +20,7 @@ */ import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; import java.util.Collection; @@ -32,8 +33,11 @@ /** * A request for deploying one or more artifacts to a remote repository. + * + * @since 4.0 */ @Experimental +@Immutable public interface ArtifactDeployerRequest { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java index 140f8dbebcea..c9f2095aa069 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactory.java @@ -27,6 +27,8 @@ /** * Service used to create {@link Artifact} objects. + * + * @since 4.0 */ @Experimental public interface ArtifactFactory extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java index 9b410af824e0..eb7e3f96cc91 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactFactoryRequest.java @@ -26,6 +26,11 @@ import org.apache.maven.api.Session; import org.apache.maven.api.annotations.NotThreadSafe; +/** + * + * + * @since 4.0 + */ @Experimental @Immutable public interface ArtifactFactoryRequest diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java index 88133f35779f..5b07a88f8420 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstaller.java @@ -28,7 +28,10 @@ import org.apache.maven.api.annotations.Experimental; /** - * @author Robert Scholte + * Installs {@link Artifact}s to the local repository. + * + * @since 4.0 + * @see Session#withLocalRepository(org.apache.maven.api.LocalRepository) */ @Experimental public interface ArtifactInstaller extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java index 4ebf173d292a..e6c6dc6abd81 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerException.java @@ -22,7 +22,7 @@ import org.apache.maven.api.annotations.Experimental; /** - * + * @since 4.0 */ @Experimental public class ArtifactInstallerException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java index 5c66c6089de9..772203a85801 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactInstallerRequest.java @@ -33,6 +33,8 @@ /** * A request for installing one or more artifacts in the local repository. + * + * @since 4.0 */ @Experimental @Immutable diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java index a65d05fb61db..4fa771343131 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactManager.java @@ -30,6 +30,10 @@ import org.apache.maven.api.Artifact; import org.apache.maven.api.Metadata; +/** + * + * @since 4.0 + */ @Experimental public interface ArtifactManager extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java index d35cb2b691dc..674ec41af7c5 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -26,6 +26,8 @@ /** * Resolves the artifact, i.e download the file when required and attach it to the artifact + * + * @since 4.0 */ @Experimental public interface ArtifactResolver extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java index fe34047c2027..ba6e5482cf34 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverException.java @@ -22,7 +22,9 @@ import org.apache.maven.api.annotations.Experimental; /** - * + * + * + * @since 4.0 */ @Experimental public class ArtifactResolverException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java index 115e7d9096c0..2f4594150139 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java @@ -29,6 +29,8 @@ /** * A request for resolving an artifact. + * + * @since 4.0 */ @Experimental @Immutable diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java index 8df51371bf1b..4d2eba4b0560 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java @@ -25,8 +25,7 @@ /** * The Artifact Result * - * @author Robert Scholte - * @since 3.0 + * @since 4.0 */ @Experimental public interface ArtifactResolverResult diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java index fe3574a6f5cc..86afa5a20d38 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/BaseRequest.java @@ -30,6 +30,8 @@ /** * Base class for requests. + * + * @since 4.0 */ @Experimental abstract class BaseRequest diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java index 89fa8ec44fbd..c06331f621b4 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java @@ -34,8 +34,7 @@ * The dependencies collection mechanism will not download any artifacts, * and only the pom files will be downloaded. * - * @author Robert Scholte - * @author Guillaume Nodet + * @since 4.0 */ @Experimental public interface DependencyCollector extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java index 86b715d535b0..019fedb6b31b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorException.java @@ -22,8 +22,10 @@ import org.apache.maven.api.annotations.Experimental; /** - * Thrown in case of bad artifact descriptors, version ranges or other issues encountered during calculation of the - * dependency graph. + * Thrown in case of bad artifact descriptors, version ranges or other + * issues encountered during calculation of the dependency graph. + * + * @since 4.0 */ @Experimental public class DependencyCollectorException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java index 7b4a84c0d699..3bc8dadfbcb0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java @@ -45,6 +45,7 @@ * retrieved from the artifact descriptor of the root dependency. And last, only direct dependencies can be specified in * which case the root node of the resulting graph has no associated dependency. * + * @since 4.0 * @see DependencyCollector#collect(DependencyCollectorRequest) */ @Experimental diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java index 67f606ba3f36..09388cca7506 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorResult.java @@ -27,6 +27,7 @@ /** * The result of a dependency collection request. * + * @since 4.0 * @see DependencyCollector#collect(DependencyCollectorRequest) */ @Experimental diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java index fe3f192d6f34..d33fa7cb53a6 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java @@ -26,6 +26,10 @@ import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; +/** + * + * @since 4.0 + */ @Experimental public interface DependencyFactory extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java index 20dd5587dd1b..4f62e8985aa9 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java @@ -32,6 +32,10 @@ import org.apache.maven.api.Exclusion; import org.apache.maven.api.annotations.NotThreadSafe; +/** + * + * @since 4.0 + */ @Experimental @Immutable public interface DependencyFactoryRequest diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java index d70285dcd91e..4f705fb2948d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java @@ -34,8 +34,7 @@ * The DependencyResolver service can be used to collect the dependencies * and download the artifacts. * - * @author Robert Scholte - * @author Guillaume Nodet + * @since 4.0 */ @Experimental public interface DependencyResolver extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java index 9ccdb737035d..9aca3afd560a 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java @@ -23,6 +23,8 @@ /** * The Exception class in case a resolving does not work. + * + * @since 4.0 */ @Experimental public class DependencyResolverException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java index 92da7b9e95f1..7485bfa35327 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java @@ -42,6 +42,8 @@ /** * A request to collect and resolve a dependency graph. + * + * @since 4.0 */ @Experimental @Immutable diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java index 27b63f6b7a90..ce5acaef5186 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java @@ -25,9 +25,8 @@ import org.apache.maven.api.annotations.Experimental; /** - * - * @author Robert Scholte * + * @since 4.0 */ @Experimental public interface DependencyResolverResult diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java index f40f7d0f2b21..5e40ac83fb01 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LocalRepositoryManager.java @@ -29,6 +29,10 @@ import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Experimental; +/** + * + * @since 4.0 + */ @Experimental public interface LocalRepositoryManager extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java index 6f5350b98412..aba7dd7219c1 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MavenException.java @@ -21,6 +21,11 @@ import org.apache.maven.api.annotations.Experimental; +/** + * Base class for all maven exceptions. + * + * @since 4.0 + */ @Experimental public class MavenException extends RuntimeException { @@ -43,8 +48,4 @@ public MavenException( Throwable cause ) super( cause ); } - public MavenException( String message, Throwable cause, boolean enableSuppression, boolean writableStackTrace ) - { - super( message, cause, enableSuppression, writableStackTrace ); - } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java index f309cd48170e..1d86911995b6 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilder.java @@ -23,6 +23,8 @@ /** * Message builder that supports configurable styling. + * + * @since 4.0 * @see MessageBuilderFactory */ public interface MessageBuilder diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java index e866b5f47054..5290dab1487d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/MessageBuilderFactory.java @@ -25,6 +25,8 @@ /** * A factory for {@link MessageBuilder}. + * + * @since 4.0 */ @Experimental public interface MessageBuilderFactory extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java index 47051a2fa95d..1c0c50813fc1 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -28,6 +28,9 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; +/** + * @since 4.0 + */ @Experimental public interface ProjectBuilder extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java index 6b72cd6b2d1e..2256bd144611 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderException.java @@ -22,7 +22,9 @@ import org.apache.maven.api.annotations.Experimental; /** - * The Exception class in case a resolving does not work. + * The Exception class throw by the {@link ProjectBuilder} service. + * + * @since 4.0 */ @Experimental public class ProjectBuilderException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java index 1e0b1c0d0162..fef6ceae0dd4 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblem.java @@ -22,12 +22,10 @@ import org.apache.maven.api.annotations.Experimental; /** - * Describes a problem that was encountered during settings building. A problem can either be an exception that was - * thrown or a simple string message. In addition, a problem carries a hint about its source, e.g. the settings file - * that exhibits the problem. + * Describes a problem that was encountered during project building. A problem can either be an exception that was + * thrown or a simple string message. In addition, a problem carries a hint about its source. * - * @author Benjamin Bentmann - * @author Robert Scholte + * @since 4.0 */ @Experimental public interface ProjectBuilderProblem diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java index 1200538b9d75..6af0257098fc 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderProblemSeverity.java @@ -23,6 +23,8 @@ /** * The different severity levels for a problem, in decreasing order. + * + * @since 4.0 */ @Experimental public enum ProjectBuilderProblemSeverity diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java index 92de03581804..3e38050aa310 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -33,6 +33,12 @@ import static org.apache.maven.api.services.BaseRequest.nonNull; +/** + * Request used to build a {@link org.apache.maven.api.Project} using + * the {@link ProjectBuilder} service. + * + * @since 4.0 + */ @Experimental @Immutable public interface ProjectBuilderRequest diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java index 5548e665886a..ba3c60fb6fc4 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java @@ -28,6 +28,11 @@ import org.apache.maven.api.Project; +/** + * Result of a project build call. + * + * @since 4.0 + */ @Experimental public interface ProjectBuilderResult { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java index 2c5c18188ddf..1add18cb12fb 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderSource.java @@ -24,6 +24,11 @@ import org.apache.maven.api.annotations.Experimental; +/** + * The source for a project's XML model. + * + * @since 4.0 + */ @Experimental public interface ProjectBuilderSource { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java index 08fc062c37fa..e8bf6f46a7f4 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -35,7 +35,9 @@ import org.apache.maven.api.Session; /** - * Interface to manage the project during its lifecycle + * Interface to manage the project during its lifecycle. + * + * @since 4.0 */ @Experimental public interface ProjectManager extends Service diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java index 6d4816a08a9a..a5229f4b4f89 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Prompter.java @@ -24,6 +24,11 @@ import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Experimental; +/** + * Service used to interact with the end user. + * + * @since 4.0 + */ @Experimental public interface Prompter extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java index 6c3fbd3e4911..4f892c749412 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/PrompterException.java @@ -22,7 +22,9 @@ import org.apache.maven.api.annotations.Experimental; /** - * The Exception class in case a the prompter can not perform a call. + * The Exception class throw by the {@link Prompter} service. + * + * @since 4.0 */ @Experimental public class PrompterException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java index 5b36b41b2e21..727a3e485f5d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/RepositoryFactory.java @@ -28,6 +28,11 @@ import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Repository; +/** + * Factory service to create {@link LocalRepository} or {@link RemoteRepository} objects. + * + * @since 4.0 + */ @Experimental public interface RepositoryFactory extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java index e3059b81f681..df893318f759 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java @@ -25,6 +25,8 @@ * Resolution scope * TODO: merge this with {@link org.apache.maven.api.plugin.annotations.ResolutionScope} * TODO: should this simply be an EnumSet instead ? + * + * @since 4.0 */ @Experimental public enum ResolutionScope diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java index 3c079011d355..9b0c54d55521 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainFactory.java @@ -22,6 +22,9 @@ import org.apache.maven.api.annotations.Consumer; import org.apache.maven.api.annotations.Experimental; +/** + * @since 4.0 + */ @Experimental @Consumer public interface ToolchainFactory diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java index fc2a4082f50f..d5c6c5779de9 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManager.java @@ -29,6 +29,11 @@ import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; +/** + * Service to manage {@link Toolchain}s. + * + * @since 4.0 + */ @Experimental public interface ToolchainManager extends Service { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java index 845ea8fad2ff..2c8a2bd8fe59 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ToolchainManagerException.java @@ -22,7 +22,9 @@ import org.apache.maven.api.annotations.Experimental; /** - * The Exception class in case a resolving does not work. + * The Exception class throw by the {@link ToolchainManager}. + * + * @since 4.0 */ @Experimental public class ToolchainManagerException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java index bb4655416d6a..ed5e69ba75c7 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParser.java @@ -26,7 +26,9 @@ import org.apache.maven.api.annotations.Nonnull; /** - * Service interface to parse version and version ranges + * Service interface to parse {@link Version} and {@link VersionRange}. + * + * @since 4.0 */ @Experimental public interface VersionParser extends Service @@ -37,6 +39,7 @@ public interface VersionParser extends Service * @param version The version string to parse, must not be {@code null}. * @return The parsed version, never {@code null}. * @throws VersionParserException If the string violates the syntax rules of this scheme. + * @see org.apache.maven.api.Session#parseVersion(String) */ @Nonnull Version parseVersion( @Nonnull String version ); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java index fca94c6e51ae..f0c4481132e2 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/VersionParserException.java @@ -22,7 +22,9 @@ import org.apache.maven.api.annotations.Experimental; /** - * The Exception class in case a resolving does not work. + * The Exception class thrown by {@link VersionParser}. + * + * @since 4.0 */ @Experimental public class VersionParserException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java index 373522fbd149..8de030ff7080 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ModelXmlFactory.java @@ -22,6 +22,11 @@ import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.model.Model; +/** + * Reads or writes a {@link Model} using XML. + * + * @since 4.0 + */ @Experimental public interface ModelXmlFactory extends XmlFactory { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java index 2fdab67a8eba..0d6672ae94f5 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/SettingsXmlFactory.java @@ -22,6 +22,11 @@ import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.settings.Settings; +/** + * Reads and writes a {@link Settings} object to/from XML. + * + * @since 4.0 + */ @Experimental public interface SettingsXmlFactory extends XmlFactory { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java index 5bbc42c865cf..854cb9791386 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/ToolchainsXmlFactory.java @@ -22,6 +22,11 @@ import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.toolchain.PersistedToolchains; +/** + * Reads and writes a {@link PersistedToolchains} object to/from XML. + * + * @since 4.0 + */ @Experimental public interface ToolchainsXmlFactory extends XmlFactory { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java index d21f256aff31..651b1a5fe8e3 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlFactory.java @@ -23,15 +23,34 @@ import java.io.OutputStream; import java.io.Reader; import java.io.Writer; +import java.nio.file.Path; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.Service; +/** + * Generic interface to read/write objects to/from XML. + * + * @param the object type to read/write + * @since 4.0 + */ @Experimental public interface XmlFactory extends Service { + @Nonnull + default T read( @Nonnull Path path ) throws XmlReaderException + { + return read( path, true ); + } + + @Nonnull + default T read( @Nonnull Path path, boolean strict ) throws XmlReaderException + { + return read( XmlReaderRequest.builder().path( path ).strict( strict ).build() ); + } + @Nonnull default T read( @Nonnull InputStream input ) throws XmlReaderException { @@ -59,6 +78,11 @@ default T read( @Nonnull Reader reader, boolean strict ) throws XmlReaderExcepti @Nonnull T read( @Nonnull XmlReaderRequest request ) throws XmlReaderException; + default void write( @Nonnull T content, @Nonnull Path path ) throws XmlWriterException + { + write( XmlWriterRequest.builder().content( content ).path( path ).build() ); + } + default void write( @Nonnull T content, @Nonnull OutputStream outputStream ) throws XmlWriterException { write( XmlWriterRequest.builder().content( content ).outputStream( outputStream ).build() ); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java index 716c812534fd..2cc30c0c26cf 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderException.java @@ -23,7 +23,9 @@ import org.apache.maven.api.services.MavenException; /** - * + * An exception thrown during the reading of an xml file. + * + * @since 4.0 */ @Experimental public class XmlReaderException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java index 20f7f621162b..05e4423039bf 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlReaderRequest.java @@ -29,6 +29,11 @@ import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.NotThreadSafe; +/** + * An XML reader request. + * + * @since 4.0 + */ @Experimental @Immutable public interface XmlReaderRequest diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java index 80fde8d59c0d..099b6ea12b19 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterException.java @@ -23,7 +23,9 @@ import org.apache.maven.api.services.MavenException; /** - * + * An exception thrown during the writing of an xml file. + * + * @since 4.0 */ @Experimental public class XmlWriterException diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java index de225a1236fd..15f0319dd81e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/xml/XmlWriterRequest.java @@ -21,13 +21,22 @@ import java.io.OutputStream; import java.io.Writer; +import java.nio.file.Path; import org.apache.maven.api.annotations.Experimental; +/** + * An XML writer request. + * + * @since 4.0 + * @param the object type to read + */ @Experimental public interface XmlWriterRequest { + Path getPath(); + OutputStream getOutputStream(); Writer getWriter(); @@ -41,10 +50,17 @@ static XmlWriterRequestBuilder builder() class XmlWriterRequestBuilder { + Path path; OutputStream outputStream; Writer writer; T content; + public XmlWriterRequestBuilder path( Path path ) + { + this.path = path; + return this; + } + public XmlWriterRequestBuilder outputStream( OutputStream outputStream ) { this.outputStream = outputStream; @@ -65,22 +81,30 @@ public XmlWriterRequestBuilder content( T content ) public XmlWriterRequest build() { - return new DefaultXmlWriterRequest<>( outputStream, writer, content ); + return new DefaultXmlWriterRequest<>( path, outputStream, writer, content ); } private static class DefaultXmlWriterRequest implements XmlWriterRequest { + final Path path; final OutputStream outputStream; final Writer writer; final T content; - DefaultXmlWriterRequest( OutputStream outputStream, Writer writer, T content ) + DefaultXmlWriterRequest( Path path, OutputStream outputStream, Writer writer, T content ) { + this.path = path; this.outputStream = outputStream; this.writer = writer; this.content = content; } + @Override + public Path getPath() + { + return path; + } + @Override public OutputStream getOutputStream() { diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java index 3e95c7480653..f8de92bb3a12 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Consumer.java @@ -20,23 +20,28 @@ */ import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * A type implemented by, or extended by maven plugins or extensions. * Maven plugins or extensions may provide implementations of those types which will be used by maven. - * + *

* A type can be marked {@link Consumer} or {@link Provider} but not both. A type is assumed to be * {@link Consumer} if it is not marked either {@link Consumer} or {@link Provider}. - * + *

* A package can be marked {@link Provider}. In this case, all types in the package are considered * to be a provider type regardless of whether they are marked {@link Consumer} or {@link Provider}. * * @see Provider + * @since 4.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.TYPE, ElementType.PACKAGE } ) public @interface Consumer { } diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java index b9ae1cf19708..bb706d893fdb 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Experimental.java @@ -26,7 +26,10 @@ /** * This annotation tags types that are part of an experimental API. * Classes or methods annotated with this annotation may be changed / removed without notice. + * + * @since 4.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) public @interface Experimental diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java index efae138c7de7..9813f69d5b22 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Generated.java @@ -20,11 +20,20 @@ */ import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +/** + * This annotation indicates that a type is automatically generated. + * + * @since 4.0 + */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) public @interface Generated { } diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java index af125a2492bf..ea8df9a06940 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Immutable.java @@ -20,12 +20,24 @@ */ import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +/** + * The {@code Immutable} annotation indicates that the object is immutable, i.e. + * none of its field can be changed. This also ensures that the type is + * {@link ThreadSafe}. + * + * @see ThreadSafe + * @since 4.0 + */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) @ThreadSafe +@Target( ElementType.TYPE ) public @interface Immutable { } diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java index 7b536e11ae38..0668a3bc8fdb 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nonnull.java @@ -20,8 +20,10 @@ */ import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * The annotated element must not be null. @@ -29,9 +31,14 @@ * Annotated fields must not be null after construction has completed. *

* When this annotation is applied to a method it applies to the method return value. + * + * @see Nullable + * @since 4.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.FIELD, ElementType.PARAMETER, ElementType.METHOD } ) public @interface Nonnull { } diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java index a69fab6abd16..ae4a6286fff7 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/NotThreadSafe.java @@ -20,11 +20,22 @@ */ import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +/** + * This annotation indicates that the annotated type is not threadsafe + * and should only be used by a single thread. + * + * @see ThreadSafe + * @since 4.0 + */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) public @interface NotThreadSafe { } diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java index e50dc3d58d36..e21a6de6a744 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Nullable.java @@ -23,6 +23,13 @@ import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +/** + * The annotated element can be {@code null}. + * + * @see Nonnull + * @since 4.0 + */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) public @interface Nullable diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java index 0bdbcfca2395..ea5174def81b 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/Provider.java @@ -20,23 +20,28 @@ */ import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; /** * A type implemented by, or extended by maven itself. * Maven provides implementations of those types and may inject them in plugins. - * + *

* A type can be marked {@link Consumer} or {@link Provider} but not both. A type is assumed to be * {@link Consumer} if it is not marked either {@link Consumer} or {@link Provider}. - * + *

* A package can be marked {@link Provider}. In this case, all types in the package are considered * to be a provider type regardless of whether they are marked {@link Consumer} or {@link Provider}. * * @see Consumer + * @since 4.0 */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) +@Target( { ElementType.TYPE, ElementType.PACKAGE } ) public @interface Provider { } diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java index 4cad58984343..82d7b8463bc4 100644 --- a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/ThreadSafe.java @@ -20,11 +20,23 @@ */ import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; import java.lang.annotation.Retention; import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; +/** + * The {@code ThreadSafe} annotation can be used to indicate a given type + * is thread safe. {@link Immutable} objects are automatically thread safe. + * + * @see Immutable + * @see NotThreadSafe + * @since 4.0 + */ +@Experimental @Documented @Retention( RetentionPolicy.CLASS ) +@Target( ElementType.TYPE ) public @interface ThreadSafe { } diff --git a/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/package-info.java b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/package-info.java new file mode 100644 index 000000000000..2a0d276c784d --- /dev/null +++ b/api/maven-api-meta/src/main/java/org/apache/maven/api/annotations/package-info.java @@ -0,0 +1,30 @@ +// CHECKSTYLE_OFF: RegexpHeader +/** + * This package contains non-functional annotations which are + * used to tag various elements and help users understanding + * how those types should be used. + * + * @since 4.0 + */ +@Experimental +package org.apache.maven.api.annotations; + +/* + * 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. + */ + diff --git a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java index 357a307fea78..2b8d63eae01b 100644 --- a/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java +++ b/api/maven-api-xml/src/main/java/org/apache/maven/api/xml/Dom.java @@ -28,8 +28,13 @@ import org.apache.maven.api.annotations.Nullable; import org.apache.maven.api.annotations.ThreadSafe; +/** + * An immutable xml node. + * + * @since 4.0 + */ @Experimental -@ThreadSafe @Immutable +@ThreadSafe @Immutable public interface Dom { diff --git a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java index d181e046bf7d..6f82631695ba 100644 --- a/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java +++ b/api/modello-plugin-velocity/src/main/java/org/codehaus/modello/plugin/velocity/VelocityGenerator.java @@ -37,11 +37,8 @@ import org.codehaus.modello.model.Model; import org.codehaus.modello.model.Version; import org.codehaus.modello.plugin.AbstractModelloGenerator; -import org.codehaus.modello.plugin.ModelloGenerator; -import org.codehaus.plexus.component.annotations.Component; import org.codehaus.plexus.util.io.CachingWriter; -@Component( role = ModelloGenerator.class, hint = "velocity" ) public class VelocityGenerator extends AbstractModelloGenerator { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java index 55a6f8796445..c8079351e1e8 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultModelXmlFactory.java @@ -24,6 +24,7 @@ import java.io.Reader; import java.io.Writer; import java.net.URL; +import java.nio.file.Files; import java.nio.file.Path; import org.apache.maven.api.annotations.Nonnull; @@ -89,11 +90,12 @@ public void write( XmlWriterRequest request ) throws XmlWriterException { nonNull( request, "request can not be null" ); Model content = nonNull( request.getContent(), "content can not be null" ); + Path path = request.getPath(); OutputStream outputStream = request.getOutputStream(); Writer writer = request.getWriter(); - if ( writer == null && outputStream == null ) + if ( writer == null && outputStream == null && path == null ) { - throw new IllegalArgumentException( "writer or outputStream must be non null" ); + throw new IllegalArgumentException( "writer, outputStream or path must be non null" ); } try { @@ -101,10 +103,17 @@ public void write( XmlWriterRequest request ) throws XmlWriterException { new MavenXpp3WriterEx().write( writer, content ); } - else + else if ( outputStream != null ) { new MavenXpp3WriterEx().write( outputStream, content ); } + else + { + try ( OutputStream os = Files.newOutputStream( path ) ) + { + new MavenXpp3WriterEx().write( outputStream, content ); + } + } } catch ( Exception e ) { diff --git a/plexus-utils/pom.xml b/plexus-utils/pom.xml index 2fc0a1ac3b5a..efbe9f8d8015 100644 --- a/plexus-utils/pom.xml +++ b/plexus-utils/pom.xml @@ -69,7 +69,7 @@ under the License. sources jar false - ${project.build.directory}/generated-sources + ${project.build.directory}/generated-sources/plexus-utils **/*.java org/codehaus/plexus/util/xml/Xpp3Dom.java, @@ -137,7 +137,7 @@ under the License. - target/generated-sources + target/generated-sources/plexus-utils From 11a251a3d1a5d914cd7f7ca0d80c2f35b341dea3 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 06:53:26 +0200 Subject: [PATCH 86/98] Split Artifact / Coordinate --- .../java/org/apache/maven/api/Artifact.java | 25 +-- .../java/org/apache/maven/api/Coordinate.java | 97 ++++++++ .../java/org/apache/maven/api/Dependency.java | 36 +-- .../java/org/apache/maven/api/Session.java | 17 +- .../main/java/org/apache/maven/api/Type.java | 72 ++++++ .../java/org/apache/maven/api/Version.java | 8 + .../maven/api/services/ArtifactResolver.java | 3 +- .../api/services/ArtifactResolverRequest.java | 29 ++- .../maven/api/services/CoordinateFactory.java | 61 ++++++ .../services/CoordinateFactoryRequest.java | 207 ++++++++++++++++++ .../maven/api/services/TypeRegistry.java | 47 ++++ .../maven/internal/impl/AbstractSession.java | 46 +++- .../maven/internal/impl/DefaultArtifact.java | 21 +- .../impl/DefaultArtifactResolver.java | 2 +- .../internal/impl/DefaultCoordinate.java | 124 +++++++++++ .../impl/DefaultCoordinateFactory.java | 62 ++++++ .../internal/impl/DefaultDependency.java | 47 +++- .../maven/internal/impl/DefaultProject.java | 40 +++- .../maven/internal/impl/DefaultSession.java | 32 ++- .../internal/impl/DefaultSessionFactory.java | 9 +- .../internal/impl/DefaultTypeRegistry.java | 84 +++++++ .../internal/impl/DefaultVersionParser.java | 11 + .../apache/maven/internal/impl/TestApi.java | 16 +- 23 files changed, 987 insertions(+), 109 deletions(-) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Coordinate.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/Type.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactoryRequest.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/TypeRegistry.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinate.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index efd15df28aeb..1d8c768e5859 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -27,11 +27,7 @@ import java.util.Optional; /** - * TODO: split between Coordinates / AttachedArtifact / ResolvedArtifact ? - * Coordinate: version range - * : version - * ResolvedArtifact: version + file - * AttachedArtifact: + * An artifact points to a resource such as a jar file or war application. * * @since 4.0 */ @@ -70,7 +66,7 @@ public interface Artifact * @return The version. */ @Nonnull - String getVersion(); + Version getVersion(); /** * The file extension of the artifact. @@ -81,21 +77,22 @@ public interface Artifact String getExtension(); /** - * Gets the base version of this artifact, for example "1.0-SNAPSHOT". In contrast to the {@link #getVersion()}, the - * base version will always refer to the unresolved version. + * The artifact type. * - * @return The base version, never {@code null}. + * @return The artifact type, never {@code null}. */ @Nonnull - String getBaseVersion(); + Type getType(); /** - * Determines whether this artifact uses a snapshot version. + * Gets the base version of this artifact, for example "1.0-SNAPSHOT". In contrast to the {@link #getVersion()}, the + * base version will always refer to the unresolved version. + * TODO: move this inside {@link Version} ? * - * @return {@code true} if the artifact is a snapshot, {@code false} otherwise. - * @see org.apache.maven.api.Session#isVersionSnapshot(String) + * @return The base version, never {@code null}. */ - boolean isSnapshot(); + @Nonnull + String getBaseVersion(); /** * Gets the file of this artifact. Note that only resolved artifacts have a file associated with them. In general, diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Coordinate.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Coordinate.java new file mode 100644 index 000000000000..2a92e2418891 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Coordinate.java @@ -0,0 +1,97 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; + +/** + * The {@code Coordinate} object is used to point to an {@link Artifact} + * but the version may be specified as a range instead of an exact version. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface Coordinate +{ + + /** + * The groupId of the artifact. + * + * @return The groupId. + */ + @Nonnull + String getGroupId(); + + /** + * The artifactId of the artifact. + * + * @return The artifactId. + */ + @Nonnull + String getArtifactId(); + + /** + * The classifier of the artifact. + * + * @return The classifier or an empty string if none, never {@code null}. + */ + @Nonnull + String getClassifier(); + + /** + * The version of the artifact. + * + * @return The version. + */ + @Nonnull + VersionRange getVersion(); + + /** + * The extension of the artifact. + * + * @return The extension or an empty string if none, never {@code null}. + */ + @Nonnull + String getExtension(); + + /** + * The type of the artifact. + * + * @return The type. + */ + @Nonnull + Type getType(); + + /** + * Unique id identifying this artifact + */ + default String getId() + { + return getGroupId() + + ":" + getArtifactId() + + ":" + getExtension() + + ( getClassifier().isEmpty() ? "" : ":" + getClassifier() ) + + ":" + getVersion(); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java index 8e25584708ec..ca611f14ab37 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -32,11 +32,8 @@ */ @Experimental @Immutable -public interface Dependency +public interface Dependency extends Coordinate { - @Nonnull - Artifact getArtifact(); - @Nonnull String getScope(); @@ -46,35 +43,4 @@ public interface Dependency @Nonnull Collection getExclusions(); - @Nonnull - default String getGroupId() - { - return getArtifact().getGroupId(); - } - - @Nonnull - default String getArtifactId() - { - return getArtifact().getArtifactId(); - } - - @Nonnull - default String getVersion() - { - return getArtifact().getVersion(); - } - - @Nonnull - default String getType() - { - // TODO - throw new UnsupportedOperationException( "Not implemented yet" ); - } - - @Nonnull - default String getClassifier() - { - return getArtifact().getClassifier(); - } - } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index a16710af1514..258d8be6c48a 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -169,6 +169,19 @@ public interface Session @Nonnull RemoteRepository createRemoteRepository( @Nonnull Repository repository ); + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String) + */ + Coordinate createCoordinate( String groupId, String artifactId, String version, String extension ); + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + Coordinate createCoordinate( String groupId, String artifactId, String version, String classifier, + String extension, String type ); + /** * Shortcut for getService(ArtifactFactory.class).create(...) * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String) @@ -184,11 +197,11 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri /** * Shortcut for getService(ArtifactResolver.class).resolve(...) - * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Artifact) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Coordinate) * * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed */ - Artifact resolveArtifact( Artifact artifact ); + Artifact resolveArtifact( Coordinate artifact ); /** * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java new file mode 100644 index 000000000000..71a94b2e28fc --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Type.java @@ -0,0 +1,72 @@ +package org.apache.maven.api; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; + +/** + * An artifact's{@code Type} represents a known kind of artifacts. + * Such types are often associated to an extension and possibly + * a classifier, for example {@code java-source} has a {@code jar} + * extension and a {@code sources} classifier. + * It is also used to determine if a given dependency should be + * included in the classpath or if its transitive dependencies should. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface Type +{ + + String POM = "pom"; + String JAR = "jar"; + String JAVA_SOURCE = "java-source"; + String JAVADOC = "javadoc"; + String MAVEN_PLUGIN = "maven-plugin"; + String TEST_JAR = "test-jar"; + + /** + * Returns the dependency type name. + * + * @return the type name + */ + String getName(); + + /** + * Get the file extension associated to the file represented by the dependency type. + * + * @return the file extension + */ + String getExtension(); + + /** + * Get the classifier associated to the dependency type. + * + * @return the classifier + */ + String getClassifier(); + + boolean isIncludesDependencies(); + + boolean isAddedToClasspath(); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java index 6c5371a3e865..4cb274a126fd 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java @@ -34,6 +34,14 @@ public interface Version extends Comparable { + /** + * Determines whether this artifact uses a snapshot version. + * + * @return {@code true} if the artifact is a snapshot, {@code false} otherwise. + * @see org.apache.maven.api.Session#isVersionSnapshot(String) + */ + boolean isSnapshot(); + /** * Returns a string representation of this version. * @return the string representation of this version diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java index 674ec41af7c5..0b125ee0bc98 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Coordinate; import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; @@ -51,7 +52,7 @@ public interface ArtifactResolver extends Service * parameter {@code coordinate} is {@code null} or invalid. */ default ArtifactResolverResult resolve( Session session, - Artifact artifact ) + Coordinate artifact ) { return resolve( ArtifactResolverRequest.build( session, artifact ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java index 2f4594150139..8c5d290168c8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java @@ -19,12 +19,11 @@ * under the License. */ +import org.apache.maven.api.Coordinate; +import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; - -import org.apache.maven.api.Session; -import org.apache.maven.api.Artifact; import org.apache.maven.api.annotations.NotThreadSafe; /** @@ -40,7 +39,7 @@ public interface ArtifactResolverRequest Session getSession(); @Nonnull - Artifact getArtifact(); + Coordinate getCoordinate(); @Nonnull static ArtifactResolverRequestBuilder builder() @@ -49,11 +48,11 @@ static ArtifactResolverRequestBuilder builder() } @Nonnull - static ArtifactResolverRequest build( Session session, Artifact artifact ) + static ArtifactResolverRequest build( Session session, Coordinate coordinate ) { return builder() .session( session ) - .artifact( artifact ) + .coordinate( coordinate ) .build(); } @@ -61,7 +60,7 @@ static ArtifactResolverRequest build( Session session, Artifact artifact ) class ArtifactResolverRequestBuilder { Session session; - Artifact artifact; + Coordinate coordinate; @Nonnull public ArtifactResolverRequestBuilder session( Session session ) @@ -71,35 +70,35 @@ public ArtifactResolverRequestBuilder session( Session session ) } @Nonnull - public ArtifactResolverRequestBuilder artifact( Artifact artifact ) + public ArtifactResolverRequestBuilder coordinate( Coordinate artifact ) { - this.artifact = artifact; + this.coordinate = artifact; return this; } @Nonnull public ArtifactResolverRequest build() { - return new DefaultArtifactResolverRequest( session, artifact ); + return new DefaultArtifactResolverRequest( session, coordinate ); } private static class DefaultArtifactResolverRequest extends BaseRequest implements ArtifactResolverRequest { @Nonnull - private final Artifact artifact; + private final Coordinate coordinate; DefaultArtifactResolverRequest( @Nonnull Session session, - @Nonnull Artifact artifact ) + @Nonnull Coordinate coordinate ) { super( session ); - this.artifact = nonNull( artifact, "artifact can not be null" ); + this.coordinate = nonNull( coordinate, "artifact can not be null" ); } @Nonnull @Override - public Artifact getArtifact() + public Coordinate getCoordinate() { - return artifact; + return coordinate; } } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java new file mode 100644 index 000000000000..0c56fe80857c --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java @@ -0,0 +1,61 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Coordinate; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Service used to create {@link Coordinate} objects. + * + * @since 4.0 + */ +@Experimental +public interface CoordinateFactory extends Service +{ + + /** + * Creates a coordinate. + * + * @param request the request holding coordinate creation parameters + * @return an {@code Artifact}, never {@code null} + * @throws IllegalArgumentException if {@code request} is null or {@code request.session} is null or invalid + */ + @Nonnull + Coordinate create( @Nonnull CoordinateFactoryRequest request ); + + @Nonnull + default Coordinate create( @Nonnull Session session, String groupId, + String artifactId, String version, String extension ) + { + return create( CoordinateFactoryRequest.build( session, groupId, artifactId, version, extension ) ); + } + + @Nonnull + default Coordinate create( @Nonnull Session session, String groupId, String artifactId, String version, + String classifier, String extension, String type ) + { + return create( CoordinateFactoryRequest.build( session, groupId, artifactId, + version, classifier, extension, type ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactoryRequest.java new file mode 100644 index 000000000000..ac474bff7fb6 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactoryRequest.java @@ -0,0 +1,207 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; + +/** + * A request for creating a {@link org.apache.maven.api.Coordinate} object. + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface CoordinateFactoryRequest +{ + + @Nonnull + Session getSession(); + + String getGroupId(); + + String getArtifactId(); + + String getVersion(); + + String getClassifier(); + + String getExtension(); + + String getType(); + + static CoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String extension ) + { + return CoordinateFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .extension( extension ) + .build(); + } + + static CoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String classifier, String extension, String type ) + { + return CoordinateFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .classifier( classifier ) + .extension( extension ) + .type( type ) + .build(); + } + + static ArtifactFactoryRequestBuilder builder() + { + return new ArtifactFactoryRequestBuilder(); + } + + @NotThreadSafe + class ArtifactFactoryRequestBuilder + { + private Session session; + private String groupId; + private String artifactId; + private String version; + private String classifier; + private String extension; + private String type; + + public ArtifactFactoryRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public ArtifactFactoryRequestBuilder groupId( String groupId ) + { + this.groupId = groupId; + return this; + } + + public ArtifactFactoryRequestBuilder artifactId( String artifactId ) + { + this.artifactId = artifactId; + return this; + } + + public ArtifactFactoryRequestBuilder version( String version ) + { + this.version = version; + return this; + } + + public ArtifactFactoryRequestBuilder classifier( String classifier ) + { + this.classifier = classifier; + return this; + } + + public ArtifactFactoryRequestBuilder extension( String extension ) + { + this.extension = extension; + return this; + } + + public ArtifactFactoryRequestBuilder type( String type ) + { + this.type = type; + return this; + } + + public CoordinateFactoryRequest build() + { + return new DefaultArtifactFactoryRequest( session, groupId, artifactId, version, + classifier, extension, type ); + } + + private static class DefaultArtifactFactoryRequest extends BaseRequest implements CoordinateFactoryRequest + { + private final String groupId; + private final String artifactId; + private final String version; + private final String classifier; + private final String extension; + private final String type; + + DefaultArtifactFactoryRequest( @Nonnull Session session, + String groupId, + String artifactId, + String version, + String classifier, + String extension, + String type ) + { + super( session ); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.classifier = classifier; + this.extension = extension; + this.type = type; + } + + @Override + public String getGroupId() + { + return groupId; + } + + @Override + public String getArtifactId() + { + return artifactId; + } + + @Override + public String getVersion() + { + return version; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getType() + { + return type; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/TypeRegistry.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/TypeRegistry.java new file mode 100644 index 000000000000..21482ba40ba2 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/TypeRegistry.java @@ -0,0 +1,47 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Service; +import org.apache.maven.api.Type; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Access to {@link Type} registry. + * + * @since 4.0 + */ +@Experimental +public interface TypeRegistry extends Service +{ + + /** + * Obtain the {@link Type} from the specified {@code id}. + * If no type is known for {@code id}, the registry will + * create a custom {@code Type} for it. + * + * @param id the id of the type to retrieve + * @return the type + */ + @Nonnull + Type getType( @Nonnull String id ); + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java index 8eb1cd8e45cb..2c47b827da72 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java @@ -34,6 +34,7 @@ import java.util.stream.Collectors; import org.apache.maven.api.Artifact; +import org.apache.maven.api.Coordinate; import org.apache.maven.api.Dependency; import org.apache.maven.api.Listener; import org.apache.maven.api.LocalRepository; @@ -54,6 +55,7 @@ import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactResolver; import org.apache.maven.api.services.ArtifactResolverException; +import org.apache.maven.api.services.CoordinateFactory; import org.apache.maven.api.services.DependencyCollector; import org.apache.maven.api.services.DependencyCollectorException; import org.apache.maven.api.services.DependencyFactory; @@ -190,12 +192,25 @@ public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact ) artifact.getArtifactId(), artifact.getClassifier(), artifact.getExtension(), - artifact.getVersion(), + artifact.getVersion().toString(), null, file ); } + public org.eclipse.aether.artifact.Artifact toArtifact( Coordinate coord ) + { + return new org.eclipse.aether.artifact.DefaultArtifact( + coord.getGroupId(), + coord.getArtifactId(), + coord.getClassifier(), + coord.getExtension(), + coord.getVersion().toString(), + null, + (File) null + ); + } + public org.eclipse.aether.metadata.Metadata toMetadata( Metadata metadata ) { /* @@ -283,6 +298,31 @@ public RemoteRepository createRemoteRepository( @Nonnull Repository repository ) .createRemote( repository ); } + /** + * Shortcut for getService(CoordinateFactory.class).create(...) + * + * @see ArtifactFactory#create(Session, String, String, String, String) + */ + @Override + public Coordinate createCoordinate( String groupId, String artifactId, String version, String extension ) + { + return getService( CoordinateFactory.class ) + .create( this, groupId, artifactId, version, extension ); + } + + /** + * Shortcut for getService(CoordinateFactory.class).create(...) + * + * @see CoordinateFactory#create(Session, String, String, String, String, String, String) + */ + @Override + public Coordinate createCoordinate( String groupId, String artifactId, String version, String classifier, + String extension, String type ) + { + return getService( CoordinateFactory.class ) + .create( this, groupId, artifactId, version, classifier, extension, type ); + } + /** * Shortcut for getService(ArtifactFactory.class).create(...) * @@ -312,10 +352,10 @@ public Artifact createArtifact( String groupId, String artifactId, String versio * Shortcut for getService(ArtifactResolver.class).resolve(...) * * @throws ArtifactResolverException if the artifact resolution failed - * @see ArtifactResolver#resolve(Session, Artifact) + * @see ArtifactResolver#resolve(Session, Coordinate) */ @Override - public Artifact resolveArtifact( Artifact artifact ) + public Artifact resolveArtifact( Coordinate artifact ) { return getService( ArtifactResolver.class ) .resolve( this, artifact ) diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java index 4116758eb67b..eb8905534282 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -19,6 +19,8 @@ * under the License. */ +import org.apache.maven.api.Type; +import org.apache.maven.api.Version; import org.apache.maven.api.annotations.Nonnull; import java.io.File; @@ -27,6 +29,8 @@ import java.util.Optional; import org.apache.maven.api.Artifact; +import org.apache.maven.api.services.TypeRegistry; +import org.eclipse.aether.artifact.ArtifactProperties; import static org.apache.maven.internal.impl.Utils.nonNull; @@ -65,9 +69,9 @@ public String getArtifactId() @Nonnull @Override - public String getVersion() + public Version getVersion() { - return artifact.getVersion(); + return session.parseVersion( artifact.getVersion() ); } @Nonnull @@ -77,6 +81,13 @@ public String getExtension() return artifact.getExtension(); } + @Override + public Type getType() + { + String type = artifact.getProperty( ArtifactProperties.TYPE, artifact.getExtension() ); + return session.getService( TypeRegistry.class ).getType( type ); + } + @Nonnull @Override public String getClassifier() @@ -91,12 +102,6 @@ public String getBaseVersion() return artifact.getBaseVersion(); } - @Override - public boolean isSnapshot() - { - return artifact.isSnapshot(); - } - @Nonnull @Override public Optional getPath() diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java index 551a99260673..dd43df913f1c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java @@ -55,7 +55,7 @@ public ArtifactResolverResult resolve( ArtifactResolverRequest request ) try { ArtifactRequest req = new ArtifactRequest() - .setArtifact( session.toArtifact( request.getArtifact() ) ) + .setArtifact( session.toArtifact( request.getCoordinate() ) ) .setRepositories( session.toRepositories( session.getRemoteRepositories() ) ); ArtifactResult res = repositorySystem.resolveArtifact( session.getSession(), req ); return new ArtifactResolverResult() diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinate.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinate.java new file mode 100644 index 000000000000..90830609f703 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinate.java @@ -0,0 +1,124 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Objects; + +import org.apache.maven.api.Coordinate; +import org.apache.maven.api.Type; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.TypeRegistry; +import org.eclipse.aether.artifact.ArtifactProperties; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +/** + * A wrapper class around a maven resolver artifact. + */ +public class DefaultCoordinate implements Coordinate +{ + private final @Nonnull AbstractSession session; + private final @Nonnull org.eclipse.aether.artifact.Artifact coordinate; + + public DefaultCoordinate( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.artifact.Artifact coordinate ) + { + this.session = nonNull( session, "session can not be null" ); + this.coordinate = nonNull( coordinate, "coordinate can not be null" ); + } + + public org.eclipse.aether.artifact.Artifact getCoordinate() + { + return coordinate; + } + + @Nonnull + @Override + public String getGroupId() + { + return coordinate.getGroupId(); + } + + @Nonnull + @Override + public String getArtifactId() + { + return coordinate.getArtifactId(); + } + + @Nonnull + @Override + public VersionRange getVersion() + { + return session.parseVersionRange( coordinate.getVersion() ); + } + + @Override + public String getExtension() + { + return coordinate.getExtension(); + } + + @Override + public Type getType() + { + String type = coordinate.getProperty( ArtifactProperties.TYPE, coordinate.getExtension() ); + return session.getService( TypeRegistry.class ).getType( type ); + } + + @Nonnull + @Override + public String getClassifier() + { + return coordinate.getClassifier(); + } + + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + DefaultCoordinate that = (DefaultCoordinate) o; + return Objects.equals( this.getGroupId(), that.getGroupId() ) + && Objects.equals( this.getArtifactId(), that.getArtifactId() ) + && Objects.equals( this.getVersion(), that.getVersion() ) + && Objects.equals( this.getClassifier(), that.getClassifier() ) + && Objects.equals( this.getType(), that.getType() ); + } + + @Override + public int hashCode() + { + return Objects.hash( getGroupId(), getArtifactId(), getVersion(), getClassifier(), getType() ); + } + + @Override + public String toString() + { + return coordinate.toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java new file mode 100644 index 000000000000..21e451819b32 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java @@ -0,0 +1,62 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import javax.inject.Named; + +import org.apache.maven.api.Coordinate; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.CoordinateFactory; +import org.apache.maven.api.services.CoordinateFactoryRequest; +import org.apache.maven.shared.utils.StringUtils; +import org.eclipse.aether.artifact.ArtifactType; + +import static org.apache.maven.internal.impl.Utils.cast; +import static org.apache.maven.internal.impl.Utils.nonNull; + +@Named +public class DefaultCoordinateFactory implements CoordinateFactory +{ + @Override + public Coordinate create( @Nonnull CoordinateFactoryRequest request ) + { + nonNull( request, "request can not be null" ); + DefaultSession session = cast( DefaultSession.class, request.getSession(), + "request.session should be a " + DefaultSession.class ); + ArtifactType type = null; + if ( request.getType() != null ) + { + type = session.getSession().getArtifactTypeRegistry().get( request.getType() ); + } + String classifier = StringUtils.isNotEmpty( request.getClassifier() ) + ? request.getClassifier() : type != null ? type.getClassifier() : null; + String extension = StringUtils.isNotEmpty( request.getExtension() ) + ? request.getExtension() : type != null ? type.getExtension() : null; + return new DefaultCoordinate( + session, + new org.eclipse.aether.artifact.DefaultArtifact( + request.getGroupId(), + request.getArtifactId(), + classifier, + extension, + request.getVersion(), + type ) ); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java index 2291ae6a7d8e..2d37c70d2e90 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java @@ -19,14 +19,16 @@ * under the License. */ -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.Nullable; - import java.util.Collection; -import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Type; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.services.TypeRegistry; +import org.eclipse.aether.artifact.ArtifactProperties; import static org.apache.maven.internal.impl.Utils.nonNull; @@ -48,11 +50,42 @@ public org.eclipse.aether.graph.Dependency getDependency() return dependency; } - @Nonnull @Override - public Artifact getArtifact() + public String getGroupId() + { + return dependency.getArtifact().getGroupId(); + } + + @Override + public String getArtifactId() + { + return dependency.getArtifact().getArtifactId(); + } + + @Override + public String getClassifier() + { + return dependency.getArtifact().getClassifier(); + } + + @Override + public VersionRange getVersion() + { + return session.parseVersionRange( dependency.getArtifact().getVersion() ); + } + + @Override + public String getExtension() + { + return dependency.getArtifact().getExtension(); + } + + @Override + public Type getType() { - return session.getArtifact( dependency.getArtifact() ); + String type = dependency.getArtifact().getProperty( ArtifactProperties.TYPE, + dependency.getArtifact().getExtension() ); + return session.getService( TypeRegistry.class ).getType( type ); } @Nonnull diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java index 7ba41d61f372..43b25066d3ac 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -19,6 +19,8 @@ * under the License. */ +import org.apache.maven.api.Type; +import org.apache.maven.api.VersionRange; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; @@ -38,6 +40,7 @@ import org.apache.maven.api.model.DependencyManagement; import org.apache.maven.api.model.Model; import org.apache.maven.api.services.ArtifactManager; +import org.apache.maven.api.services.TypeRegistry; import org.apache.maven.project.MavenProject; public class DefaultProject implements Project @@ -146,12 +149,41 @@ private Dependency toDependency( org.apache.maven.api.model.Dependency dependenc { return new Dependency() { - @Nonnull @Override - public Artifact getArtifact() + public String getGroupId() + { + return dependency.getGroupId(); + } + + @Override + public String getArtifactId() + { + return dependency.getArtifactId(); + } + + @Override + public String getClassifier() + { + return dependency.getClassifier(); + } + + @Override + public VersionRange getVersion() + { + return session.parseVersionRange( dependency.getVersion() ); + } + + @Override + public String getExtension() + { + return getType().getExtension(); + } + + @Override + public Type getType() { - return session.createArtifact( dependency.getGroupId(), dependency.getArtifactId(), - dependency.getVersion(), null, null, dependency.getType() ); + String type = dependency.getType(); + return session.getService( TypeRegistry.class ).getType( type ); } @Nonnull diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index e05eb0fb20c6..8fd40d487ecb 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -46,6 +46,7 @@ import org.apache.maven.api.services.ArtifactInstaller; import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactResolver; +import org.apache.maven.api.services.CoordinateFactory; import org.apache.maven.api.services.DependencyCollector; import org.apache.maven.api.services.DependencyFactory; import org.apache.maven.api.services.DependencyResolver; @@ -57,11 +58,13 @@ import org.apache.maven.api.services.Prompter; import org.apache.maven.api.services.RepositoryFactory; import org.apache.maven.api.services.ToolchainManager; +import org.apache.maven.api.services.TypeRegistry; import org.apache.maven.api.services.VersionParser; import org.apache.maven.api.services.xml.ModelXmlFactory; import org.apache.maven.api.services.xml.SettingsXmlFactory; import org.apache.maven.api.services.xml.ToolchainsXmlFactory; import org.apache.maven.api.settings.Settings; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.MavenSession; @@ -94,6 +97,7 @@ public class DefaultSession extends AbstractSession private final PlexusContainer container; private final MojoExecutionScope mojoExecutionScope; private final RuntimeInformation runtimeInformation; + private final ArtifactHandlerManager artifactHandlerManager; @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultSession( @Nonnull MavenSession session, @@ -104,7 +108,8 @@ public DefaultSession( @Nonnull MavenSession session, @Nonnull DefaultToolchainManagerPrivate toolchainManagerPrivate, @Nonnull PlexusContainer container, @Nonnull MojoExecutionScope mojoExecutionScope, - @Nonnull RuntimeInformation runtimeInformation ) + @Nonnull RuntimeInformation runtimeInformation, + @Nonnull ArtifactHandlerManager artifactHandlerManager ) { this.mavenSession = nonNull( session ); this.session = mavenSession.getRepositorySession(); @@ -121,6 +126,7 @@ public DefaultSession( @Nonnull MavenSession session, this.runtimeInformation = runtimeInformation; this.artifactManager = new DefaultArtifactManager( this ); this.projectManager = new DefaultProjectManager( this, artifactManager, container ); + this.artifactHandlerManager = artifactHandlerManager; } public MavenSession getMavenSession() @@ -286,7 +292,7 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) MavenSession newSession = new MavenSession( mavenSession.getContainer(), repoSession, mavenSession.getRequest(), mavenSession.getResult() ); return new DefaultSession( newSession, repositorySystem, repositories, projectBuilder, mavenRepositorySystem, - toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation ); + toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation, artifactHandlerManager ); } @Nonnull @@ -294,7 +300,7 @@ public Session withLocalRepository( @Nonnull LocalRepository localRepository ) public Session withRemoteRepositories( @Nonnull List repositories ) { return new DefaultSession( mavenSession, repositorySystem, repositories, projectBuilder, mavenRepositorySystem, - toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation ); + toolchainManagerPrivate, container, mojoExecutionScope, runtimeInformation, artifactHandlerManager ); } @Nonnull @@ -378,6 +384,14 @@ else if ( clazz == VersionParser.class ) { return (T) new DefaultVersionParser(); } + else if ( clazz == CoordinateFactory.class ) + { + return (T) new DefaultCoordinateFactory(); + } + else if ( clazz == TypeRegistry.class ) + { + return (T) new DefaultTypeRegistry( artifactHandlerManager ); + } throw new NoSuchElementException( clazz.getName() ); } @@ -433,19 +447,15 @@ public org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ) } else { - String typeId = dependency.getType(); - org.eclipse.aether.artifact.ArtifactType type = typeId != null - ? session.getArtifactTypeRegistry().get( typeId ) : null; - String extension = type != null ? type.getExtension() : null; return new org.eclipse.aether.graph.Dependency( new org.eclipse.aether.artifact.DefaultArtifact( dependency.getGroupId(), dependency.getArtifactId(), dependency.getClassifier(), - extension, - dependency.getVersion(), - type - ), null ); + dependency.getType().getExtension(), + dependency.getVersion().toString(), + null ), + dependency.getScope() ); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java index d8fab05ef82c..4816006abb71 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSessionFactory.java @@ -24,6 +24,7 @@ import javax.inject.Singleton; import org.apache.maven.api.Session; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.scope.internal.MojoExecutionScope; @@ -45,6 +46,7 @@ public class DefaultSessionFactory private final PlexusContainer plexusContainer; private final MojoExecutionScope mojoExecutionScope; private final RuntimeInformation runtimeInformation; + private final ArtifactHandlerManager artifactHandlerManager; @Inject @SuppressWarnings( "checkstyle:ParameterNumber" ) @@ -54,7 +56,8 @@ public DefaultSessionFactory( RepositorySystem repositorySystem, DefaultToolchainManagerPrivate toolchainManagerPrivate, PlexusContainer plexusContainer, MojoExecutionScope mojoExecutionScope, - RuntimeInformation runtimeInformation ) + RuntimeInformation runtimeInformation, + ArtifactHandlerManager artifactHandlerManager ) { this.repositorySystem = repositorySystem; this.projectBuilder = projectBuilder; @@ -63,6 +66,7 @@ public DefaultSessionFactory( RepositorySystem repositorySystem, this.plexusContainer = plexusContainer; this.mojoExecutionScope = mojoExecutionScope; this.runtimeInformation = runtimeInformation; + this.artifactHandlerManager = artifactHandlerManager; } public Session getSession( MavenSession mavenSession ) @@ -75,6 +79,7 @@ private Session newSession( MavenSession mavenSession ) { return new DefaultSession( mavenSession, repositorySystem, null, projectBuilder, mavenRepositorySystem, - toolchainManagerPrivate, plexusContainer, mojoExecutionScope, runtimeInformation ); + toolchainManagerPrivate, plexusContainer, mojoExecutionScope, runtimeInformation, + artifactHandlerManager ); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java new file mode 100644 index 000000000000..c302752f8d02 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultTypeRegistry.java @@ -0,0 +1,84 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import org.apache.maven.api.Type; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.TypeRegistry; +import org.apache.maven.artifact.handler.ArtifactHandler; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultTypeRegistry implements TypeRegistry +{ + + private final ArtifactHandlerManager manager; + + public DefaultTypeRegistry( ArtifactHandlerManager manager ) + { + this.manager = nonNull( manager, "artifactHandlerManager" ); + } + + @Override + @Nonnull + public Type getType( String id ) + { + // Copy data as the ArtifacHandler is not immutable, but Type should be. + ArtifactHandler handler = manager.getArtifactHandler( nonNull( id , "id" ) ); + String extension = handler.getExtension(); + String classifier = handler.getClassifier(); + boolean includeDependencies = handler.isIncludesDependencies(); + boolean addedToClasspath = handler.isAddedToClasspath(); + return new Type() + { + @Override + public String getName() + { + return id; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public boolean isIncludesDependencies() + { + return includeDependencies; + } + + @Override + public boolean isAddedToClasspath() + { + return addedToClasspath; + } + }; + } + +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java index 376745fdcf25..900326800b51 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java @@ -58,6 +58,11 @@ public VersionRange parseVersionRange( String range ) @Override public boolean isSnapshot( String version ) + { + return checkSnapshot( version ); + } + + private static boolean checkSnapshot( String version ) { return version.endsWith( SNAPSHOT ) || SNAPSHOT_TIMESTAMP.matcher( version ).matches(); } @@ -71,6 +76,12 @@ static class DefaultVersion implements Version this.delegate = delegate; } + @Override + public boolean isSnapshot() + { + return checkSnapshot( delegate.toString() ); + } + @Override public int compareTo( Version o ) { diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index 4b03dd74d291..49be1709226d 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -24,6 +24,8 @@ import java.nio.file.Paths; import java.util.Collections; +import org.apache.maven.api.Coordinate; +import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; @@ -80,6 +82,9 @@ public class TestApi @Inject RuntimeInformation runtimeInformation; + @Inject + ArtifactHandlerManager artifactHandlerManager; + @BeforeEach void setup() { @@ -89,7 +94,8 @@ void setup() DefaultSession session = new DefaultSession( ms, repositorySystem, Collections.emptyList(), projectBuilder, mavenRepositorySystem, toolchainManagerPrivate, - plexusContainer, mojoExecutionScope, runtimeInformation ); + plexusContainer, mojoExecutionScope, runtimeInformation, + artifactHandlerManager ); DefaultLocalRepository localRepository = new DefaultLocalRepository( new LocalRepository( "target/test-classes/apiv4-repo" ) ); org.apache.maven.api.RemoteRepository remoteRepository = session.getRemoteRepository( @@ -103,11 +109,9 @@ void setup() @Test void testCreateAndResolveArtifact() throws Exception { - Artifact artifact = session.createArtifact( "org.codehaus.plexus", "plexus-utils", "1.4.5", "pom" ); - assertFalse( artifact.getPath().isPresent() ); + Coordinate coord = session.createCoordinate( "org.codehaus.plexus", "plexus-utils", "1.4.5", "pom" ); - Artifact resolved = session.resolveArtifact( artifact ); - assertNotSame( resolved, artifact ); + Artifact resolved = session.resolveArtifact( coord ); assertTrue( resolved.getPath().isPresent() ); assertNotNull( resolved.getPath().get() ); @@ -117,7 +121,7 @@ void testCreateAndResolveArtifact() throws Exception .getProject().get(); assertNotNull( project ); - artifact = session.createArtifact( "org.codehaus.plexus", "plexus-container-default", "1.0-alpha-32", "jar" ); + Artifact artifact = session.createArtifact( "org.codehaus.plexus", "plexus-container-default", "1.0-alpha-32", "jar" ); Node root = session.collectDependencies( artifact ); assertNotNull( root ); } From 1a1ce010d4ff923da64a4e9d62ab3004f2b8b9d2 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 08:39:54 +0200 Subject: [PATCH 87/98] Clean scope related api --- .../java/org/apache/maven/api/Dependency.java | 2 +- .../java/org/apache/maven/api/EventType.java | 38 +++++++++---------- .../annotations => }/ResolutionScope.java | 27 +++++++++---- .../ResolutionScope.java => Scope.java} | 38 ++++++++++++++----- .../maven/api/plugin/annotations/Mojo.java | 1 + .../maven/api/services/ProjectManager.java | 1 + .../internal/impl/DefaultDependency.java | 5 ++- .../maven/internal/impl/DefaultProject.java | 6 +-- .../internal/impl/DefaultProjectManager.java | 26 ++----------- .../maven/internal/impl/DefaultSession.java | 2 +- 10 files changed, 78 insertions(+), 68 deletions(-) rename api/maven-api-core/src/main/java/org/apache/maven/api/{plugin/annotations => }/ResolutionScope.java (74%) rename api/maven-api-core/src/main/java/org/apache/maven/api/{services/ResolutionScope.java => Scope.java} (63%) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java index ca611f14ab37..2f9d19dbf7a9 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -35,7 +35,7 @@ public interface Dependency extends Coordinate { @Nonnull - String getScope(); + Scope getScope(); @Nullable Boolean getOptional(); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java index ad81a2af5da8..0279d1222573 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/EventType.java @@ -24,30 +24,26 @@ /** * The possible types of execution events. * - * TODO: those values are lower cased, while other events are upper-case - * we need to align on one strategy - * see also {@link MetadataStorage} and {@link org.apache.maven.api.services.ResolutionScope} - * * @since 4.0 */ @Experimental public enum EventType { - ProjectDiscoveryStarted, - SessionStarted, - SessionEnded, - ProjectSkipped, - ProjectStarted, - ProjectSucceeded, - ProjectFailed, - MojoSkipped, - MojoStarted, - MojoSucceeded, - MojoFailed, - ForkStarted, - ForkSucceeded, - ForkFailed, - ForkedProjectStarted, - ForkedProjectSucceeded, - ForkedProjectFailed, + PROJECT_DISCOVERY_STARTED, + SESSION_STARTED, + SESSION_ENDED, + PROJECT_SKIPPED, + PROJECT_STARTED, + PROJECT_SUCCEEDED, + PROJECT_FAILED, + MOJO_SKIPPED, + MOJO_STARTED, + MOJO_SUCCEEDED, + MOJO_FAILED, + FORK_STARTED, + FORK_SUCCEEDED, + FORK_FAILED, + FORKED_PROJECT_STARTED, + FORKED_PROJECT_SUCCEEDED, + FORKED_PROJECT_FAILED, } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java similarity index 74% rename from api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java index 6c93c6c7255a..26839de6927b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java @@ -1,4 +1,4 @@ -package org.apache.maven.api.plugin.annotations; +package org.apache.maven.api; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,6 +19,11 @@ * under the License. */ +import java.util.Arrays; +import java.util.Collections; +import java.util.HashSet; +import java.util.Set; + import org.apache.maven.api.annotations.Experimental; /** @@ -41,38 +46,46 @@ public enum ResolutionScope * compile resolution scope * = compile + system + provided dependencies */ - COMPILE( "compile" ), + COMPILE( "compile", Scope.COMPILE, Scope.SYSTEM, Scope.PROVIDED ), /** * compile+runtime resolution scope (Maven 3 only) * = compile + system + provided + runtime dependencies */ - COMPILE_PLUS_RUNTIME( "compile+runtime" ), + COMPILE_PLUS_RUNTIME( "compile+runtime", Scope.COMPILE, Scope.SYSTEM, Scope.PROVIDED, Scope.RUNTIME ), /** * runtime resolution scope * = compile + runtime dependencies */ - RUNTIME( "runtime" ), + RUNTIME( "runtime", Scope.COMPILE, Scope.RUNTIME ), /** * runtime+system resolution scope (Maven 3 only) * = compile + system + runtime dependencies */ - RUNTIME_PLUS_SYSTEM( "runtime+system" ), + RUNTIME_PLUS_SYSTEM( "runtime+system", Scope.COMPILE, Scope.SYSTEM, Scope.RUNTIME ), /** * test resolution scope * = compile + system + provided + runtime + test * dependencies */ - TEST( "test" ); + TEST( "test", Scope.COMPILE, Scope.SYSTEM, Scope.PROVIDED, Scope.RUNTIME, Scope.TEST ); private final String id; + private final Set scopes; - ResolutionScope( String id ) + ResolutionScope( String id, Scope... scopes ) { this.id = id; + this.scopes = Collections.unmodifiableSet( new HashSet<>( Arrays.asList( scopes ) ) ); } public String id() { return this.id; } + + public Set scopes() + { + return scopes; + } + } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Scope.java similarity index 63% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/Scope.java index df893318f759..f246e9fd7f5e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Scope.java @@ -1,4 +1,4 @@ -package org.apache.maven.api.services; +package org.apache.maven.api; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -19,21 +19,39 @@ * under the License. */ +import java.util.Locale; + import org.apache.maven.api.annotations.Experimental; /** - * Resolution scope - * TODO: merge this with {@link org.apache.maven.api.plugin.annotations.ResolutionScope} - * TODO: should this simply be an EnumSet instead ? + * Scope for a dependency * * @since 4.0 */ @Experimental -public enum ResolutionScope +public enum Scope { - Compile, - CompileRuntime, - Runtime, - RuntimeSystem, - Test + COMPILE( "compile" ), + PROVIDED ( "provided" ), + SYSTEM( "system" ), + RUNTIME( "runtime" ), + TEST( "test" ), + IMPORT( "import" ); + + private final String id; + + Scope( String id ) + { + this.id = id; + } + + public String id() + { + return this.id; + } + + public static Scope get( String scope ) + { + return Enum.valueOf( Scope.class, scope.toUpperCase( Locale.ROOT ) ); + } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java index 588a64fba837..e87341140d1c 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/plugin/annotations/Mojo.java @@ -26,6 +26,7 @@ import java.lang.annotation.RetentionPolicy; import java.lang.annotation.Target; +import org.apache.maven.api.ResolutionScope; import org.apache.maven.api.annotations.Experimental; /** diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java index e8bf6f46a7f4..e649d42f5478 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -32,6 +32,7 @@ import org.apache.maven.api.Node; import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.ResolutionScope; import org.apache.maven.api.Session; /** diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java index 2d37c70d2e90..be723e489ac5 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java @@ -23,6 +23,7 @@ import org.apache.maven.api.Dependency; import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Scope; import org.apache.maven.api.Type; import org.apache.maven.api.VersionRange; import org.apache.maven.api.annotations.Nonnull; @@ -90,9 +91,9 @@ public Type getType() @Nonnull @Override - public String getScope() + public Scope getScope() { - return dependency.getScope(); + return Scope.get( dependency.getScope() ); } @Nullable diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java index 43b25066d3ac..3c918b28c6f3 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Scope; import org.apache.maven.api.Type; import org.apache.maven.api.VersionRange; import org.apache.maven.api.annotations.Nonnull; @@ -29,7 +30,6 @@ import java.util.Collection; import java.util.Collections; import java.util.List; -import java.util.Locale; import java.util.Optional; import org.apache.maven.RepositoryUtils; @@ -188,9 +188,9 @@ public Type getType() @Nonnull @Override - public String getScope() + public Scope getScope() { - return dependency.getScope().toUpperCase( Locale.ROOT ); + return Scope.get( dependency.getScope() ); } @Override diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java index 0a06ab00e6df..3626303106b5 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java @@ -20,7 +20,6 @@ */ import java.nio.file.Path; -import java.util.Arrays; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -33,24 +32,19 @@ import org.apache.maven.api.Node; import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.ResolutionScope; +import org.apache.maven.api.Scope; import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.MavenException; import org.apache.maven.api.services.ProjectManager; -import org.apache.maven.api.services.ResolutionScope; import org.apache.maven.lifecycle.LifecycleExecutionException; import org.apache.maven.lifecycle.internal.LifecycleDependencyResolver; import org.apache.maven.project.MavenProject; import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import static org.apache.maven.artifact.Artifact.SCOPE_COMPILE; -import static org.apache.maven.artifact.Artifact.SCOPE_PROVIDED; -import static org.apache.maven.artifact.Artifact.SCOPE_RUNTIME; -import static org.apache.maven.artifact.Artifact.SCOPE_SYSTEM; -import static org.apache.maven.artifact.Artifact.SCOPE_TEST; - public class DefaultProjectManager implements ProjectManager { @@ -171,21 +165,7 @@ private MavenProject getMavenProject( Project project ) private Collection toScopes( ResolutionScope scope ) { - switch ( scope ) - { - case Compile: - return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_PROVIDED ); - case Runtime: - return Arrays.asList( SCOPE_COMPILE, SCOPE_RUNTIME ); - case CompileRuntime: - return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_PROVIDED, SCOPE_RUNTIME ); - case RuntimeSystem: - return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_RUNTIME ); - case Test: - return Arrays.asList( SCOPE_COMPILE, SCOPE_SYSTEM, SCOPE_PROVIDED, SCOPE_RUNTIME, SCOPE_TEST ); - default: - throw new IllegalArgumentException(); - } + return scope.scopes().stream().map( Scope::id ).collect( Collectors.toList() ); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index 8fd40d487ecb..970593ad94c9 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -455,7 +455,7 @@ public org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ) dependency.getType().getExtension(), dependency.getVersion().toString(), null ), - dependency.getScope() ); + dependency.getScope().id() ); } } From 55e10987d293e23cf223d7d283222e8a93ffa04c Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 11:00:37 +0200 Subject: [PATCH 88/98] Fixes --- .../internal/impl/DefaultVersionParser.java | 22 +++++++++++++++++++ .../internal/DefaultMavenPluginManager.java | 2 +- 2 files changed, 23 insertions(+), 1 deletion(-) diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java index 900326800b51..d0b4b2a3aec7 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java @@ -19,6 +19,7 @@ * under the License. */ +import java.util.Objects; import java.util.regex.Pattern; import org.apache.maven.api.Version; @@ -95,6 +96,27 @@ public int compareTo( Version o ) } } + @Override + public boolean equals( Object o ) + { + if ( this == o ) + { + return true; + } + if ( o == null || getClass() != o.getClass() ) + { + return false; + } + DefaultVersion that = (DefaultVersion) o; + return delegate.equals( that.delegate ); + } + + @Override + public int hashCode() + { + return Objects.hash( delegate ); + } + @Override public String toString() { diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java index a14f891059d2..de249c727aef 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultMavenPluginManager.java @@ -650,7 +650,7 @@ private void populateMojoExecutionFields( Object mojo, String executionId, MojoD if ( StringUtils.isEmpty( configuratorId ) ) { - configuratorId = "basic"; + configuratorId = mojoDescriptor.isV4Api() ? "enhanced" : "basic"; } try From 444886f68907dae198c2e5972720e0527134aa28 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 20:59:53 +0200 Subject: [PATCH 89/98] Make sure Project and MojoExecution are seeded in the MojoExecutionScope --- .../execution/scope/internal/MojoExecutionScopeModule.java | 7 ++++--- .../org/apache/maven/plugin/DefaultBuildPluginManager.java | 5 +++++ 2 files changed, 9 insertions(+), 3 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java index adad347a8208..0420b6054e40 100644 --- a/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java +++ b/maven-core/src/main/java/org/apache/maven/execution/scope/internal/MojoExecutionScopeModule.java @@ -19,6 +19,7 @@ * under the License. */ +import com.google.inject.AbstractModule; import org.apache.maven.api.plugin.Log; import org.apache.maven.execution.scope.MojoExecutionScoped; import org.apache.maven.plugin.MojoExecution; @@ -26,8 +27,6 @@ import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.component.repository.exception.ComponentLookupException; -import com.google.inject.AbstractModule; - /** * MojoExecutionScopeModule */ @@ -52,10 +51,12 @@ protected void configure() { bindScope( MojoExecutionScoped.class, scope ); bind( MojoExecutionScope.class ).toInstance( scope ); - bind( MavenProject.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); bind( MojoExecution.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); bind( Log.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); + bind( org.apache.maven.api.Project.class ).toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); + bind( org.apache.maven.api.MojoExecution.class ) + .toProvider( MojoExecutionScope.seededKeyProvider() ).in( scope ); } } diff --git a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java index 828f5377267b..a5c284458a5b 100644 --- a/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java +++ b/maven-core/src/main/java/org/apache/maven/plugin/DefaultBuildPluginManager.java @@ -27,12 +27,15 @@ import javax.inject.Named; import javax.inject.Singleton; +import org.apache.maven.api.Project; import org.apache.maven.api.plugin.MojoException; import org.apache.maven.execution.MavenSession; import org.apache.maven.execution.MojoExecutionEvent; import org.apache.maven.execution.MojoExecutionListener; import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.internal.impl.DefaultLog; +import org.apache.maven.internal.impl.DefaultMojoExecution; +import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.descriptor.MojoDescriptor; import org.apache.maven.plugin.descriptor.PluginDescriptor; @@ -126,6 +129,8 @@ public void executeMojo( MavenSession session, MojoExecution mojoExecution ) scope.seed( MojoExecution.class, mojoExecution ); scope.seed( org.apache.maven.api.plugin.Log.class, new DefaultLog( LoggerFactory.getLogger( mojoExecution.getMojoDescriptor().getFullGoalName() ) ) ); + scope.seed( Project.class, ( ( DefaultSession) session.getSession() ).getProject( project ) ); + scope.seed( org.apache.maven.api.MojoExecution.class, new DefaultMojoExecution( mojoExecution ) ); if ( mojoDescriptor.isV4Api() ) { From c2cb7d288c2e470e0b89908944b98dacc6fc6c30 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 21:06:04 +0200 Subject: [PATCH 90/98] Add MojoExecution.getConfiguration and toString --- .../java/org/apache/maven/api/MojoExecution.java | 6 ++++++ .../internal/impl/DefaultMojoExecution.java | 16 ++++++++++++++++ 2 files changed, 22 insertions(+) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java index 945e59185f63..0d7ffd1a3499 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/MojoExecution.java @@ -19,10 +19,13 @@ * under the License. */ +import java.util.Optional; + import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.xml.Dom; /** * A {@code MojoExecution} @@ -38,4 +41,7 @@ public interface MojoExecution @Nonnull String getGoal(); + + @Nonnull + Optional getConfiguration(); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java index 4080b20cf158..c0ec2bebf18a 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultMojoExecution.java @@ -19,8 +19,12 @@ * under the License. */ +import java.util.Optional; + import org.apache.maven.api.MojoExecution; import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.xml.Dom; +import org.codehaus.plexus.util.xml.Xpp3Dom; public class DefaultMojoExecution implements MojoExecution @@ -54,4 +58,16 @@ public String getGoal() { return delegate.getGoal(); } + + @Override + public Optional getConfiguration() + { + return Optional.of( delegate.getConfiguration() ).map( Xpp3Dom::getDom ); + } + + @Override + public String toString() + { + return delegate.toString(); + } } From f5dce02795d4135ce00c2f7662e7877eaef7e133 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 21:06:43 +0200 Subject: [PATCH 91/98] Use the new computeIfAbsent --- .../apache/maven/internal/impl/DefaultSession.java | 11 +---------- 1 file changed, 1 insertion(+), 10 deletions(-) diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index 970593ad94c9..749d1f1ad4a0 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -258,16 +258,7 @@ public Object get( @Nonnull Object key ) @Override public Object computeIfAbsent( @Nonnull Object key, @Nonnull Supplier supplier ) { - // return data.computeIfAbsent( key, supplier ); - Object value = data.get( key ); - if ( value == null ) - { - if ( !data.set( key, null, supplier.get() ) ) - { - value = data.get( key ); - } - } - return value; + return data.computeIfAbsent( key, supplier ); } }; } From 60eb1af97009db4a706e53f212172149b54d4e55 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 21:07:52 +0200 Subject: [PATCH 92/98] Use a top level class for event --- .../maven/internal/impl/DefaultEvent.java | 71 +++++++++++++++++ .../maven/internal/impl/EventSpyImpl.java | 77 +------------------ 2 files changed, 72 insertions(+), 76 deletions(-) create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultEvent.java diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultEvent.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultEvent.java new file mode 100644 index 000000000000..12f047fec67f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultEvent.java @@ -0,0 +1,71 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Optional; + +import org.apache.maven.api.Event; +import org.apache.maven.api.EventType; +import org.apache.maven.api.MojoExecution; +import org.apache.maven.api.Project; +import org.apache.maven.api.Session; +import org.apache.maven.execution.ExecutionEvent; + +public class DefaultEvent implements Event +{ + private final AbstractSession session; + private final ExecutionEvent delegate; + + public DefaultEvent( AbstractSession session, ExecutionEvent delegate ) + { + this.session = session; + this.delegate = delegate; + } + + @Override + public EventType getType() + { + return EventType.valueOf( delegate.getType().name() ); + } + + @Override + public Session getSession() + { + return session; + } + + @Override + public Optional getProject() + { + return Optional.ofNullable( delegate.getProject() ).map( session::getProject ); + } + + @Override + public Optional getMojoExecution() + { + return Optional.ofNullable( delegate.getMojoExecution() ).map( DefaultMojoExecution::new ); + } + + @Override + public Optional getException() + { + return Optional.empty(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java b/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java index 6759c5bf1268..255625e49193 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/EventSpyImpl.java @@ -24,15 +24,9 @@ import javax.inject.Singleton; import java.util.Collection; -import java.util.Optional; import org.apache.maven.api.Event; -import org.apache.maven.api.EventType; import org.apache.maven.api.Listener; -import org.apache.maven.api.MojoExecution; -import org.apache.maven.api.Project; -import org.apache.maven.api.Session; -import org.apache.maven.api.model.Plugin; import org.apache.maven.eventspy.EventSpy; import org.apache.maven.execution.ExecutionEvent; @@ -64,7 +58,7 @@ public void onEvent( Object arg ) throws Exception Collection listeners = session.getListeners(); if ( !listeners.isEmpty() ) { - Event event = new EventWrapper( session, ee ); + Event event = new DefaultEvent( session, ee ); for ( Listener listener : listeners ) { listener.onEvent( event ); @@ -78,73 +72,4 @@ public void close() throws Exception { } - static class MojoExecutionWrapper implements MojoExecution - { - private final org.apache.maven.plugin.MojoExecution delegate; - - MojoExecutionWrapper( org.apache.maven.plugin.MojoExecution delegate ) - { - this.delegate = delegate; - } - - @Override - public Plugin getPlugin() - { - return delegate.getPlugin().getDelegate(); - } - - @Override - public String getExecutionId() - { - return delegate.getExecutionId(); - } - - @Override - public String getGoal() - { - return delegate.getGoal(); - } - } - - static class EventWrapper implements Event - { - private final AbstractSession session; - private final ExecutionEvent delegate; - - EventWrapper( AbstractSession session, ExecutionEvent delegate ) - { - this.session = session; - this.delegate = delegate; - } - - @Override - public EventType getType() - { - return EventType.valueOf( delegate.getType().name() ); - } - - @Override - public Session getSession() - { - return session; - } - - @Override - public Optional getProject() - { - return Optional.ofNullable( delegate.getProject() ).map( session::getProject ); - } - - @Override - public Optional getMojoExecution() - { - return Optional.ofNullable( delegate.getMojoExecution() ).map( MojoExecutionWrapper::new ); - } - - @Override - public Optional getException() - { - return Optional.empty(); - } - } } From 9eda722148e583e91d21fe3d0c576482e38d47b6 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 22 Sep 2022 22:01:13 +0200 Subject: [PATCH 93/98] Fix failing unit test --- .../org/apache/maven/AbstractCoreMavenComponentTestCase.java | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java index bb3574ae41d8..43f1e9564d3a 100644 --- a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java +++ b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java @@ -32,6 +32,7 @@ import org.apache.maven.execution.DefaultMavenExecutionResult; import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; +import org.apache.maven.internal.impl.DefaultSession; import org.apache.maven.model.Build; import org.apache.maven.model.Dependency; import org.apache.maven.model.Exclusion; @@ -48,6 +49,7 @@ import org.codehaus.plexus.PlexusContainer; import org.codehaus.plexus.util.FileUtils; import org.eclipse.aether.DefaultRepositorySystemSession; +import org.eclipse.aether.internal.impl.DefaultRepositorySystem; import org.eclipse.aether.internal.impl.SimpleLocalRepositoryManagerFactory; import org.eclipse.aether.repository.LocalRepository; @@ -166,6 +168,9 @@ protected MavenSession createMavenSession( File pom, Properties executionPropert new DefaultMavenExecutionResult() ); session.setProjects( projects ); session.setAllProjects( session.getProjects() ); + session.setSession( new DefaultSession( session, new DefaultRepositorySystem(), null, + null, null, null, null, null, + null, null ) ); return session; } From 15ca4f0145520aefe6354b533cf0d54225dd8ec9 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 23 Sep 2022 16:51:02 +0200 Subject: [PATCH 94/98] Move back the isSnapshot() method to Artifact --- .../src/main/java/org/apache/maven/api/Artifact.java | 8 ++++++++ .../src/main/java/org/apache/maven/api/Version.java | 7 ------- .../org/apache/maven/internal/impl/DefaultArtifact.java | 7 +++++++ .../apache/maven/internal/impl/DefaultVersionParser.java | 8 +------- 4 files changed, 16 insertions(+), 14 deletions(-) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index 1d8c768e5859..65322716b872 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -94,6 +94,14 @@ public interface Artifact @Nonnull String getBaseVersion(); + /** + * Determines whether this artifact uses a snapshot version. + * + * @return {@code true} if the artifact is a snapshot, {@code false} otherwise. + * @see org.apache.maven.api.Session#isVersionSnapshot(String) + */ + boolean isSnapshot(); + /** * Gets the file of this artifact. Note that only resolved artifacts have a file associated with them. In general, * callers must not assume any relationship between an artifact's filename and its coordinates. diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java index 4cb274a126fd..e84057bd4d72 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java @@ -34,13 +34,6 @@ public interface Version extends Comparable { - /** - * Determines whether this artifact uses a snapshot version. - * - * @return {@code true} if the artifact is a snapshot, {@code false} otherwise. - * @see org.apache.maven.api.Session#isVersionSnapshot(String) - */ - boolean isSnapshot(); /** * Returns a string representation of this version. diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java index eb8905534282..8ab5ec173bf6 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -102,6 +102,13 @@ public String getBaseVersion() return artifact.getBaseVersion(); } + @Override + public boolean isSnapshot() + { + return DefaultVersionParser.checkSnapshot( artifact.toString() ); + } + + @Nonnull @Override public Optional getPath() diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java index d0b4b2a3aec7..b7e406fa3e39 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java @@ -63,7 +63,7 @@ public boolean isSnapshot( String version ) return checkSnapshot( version ); } - private static boolean checkSnapshot( String version ) + static boolean checkSnapshot( String version ) { return version.endsWith( SNAPSHOT ) || SNAPSHOT_TIMESTAMP.matcher( version ).matches(); } @@ -77,12 +77,6 @@ static class DefaultVersion implements Version this.delegate = delegate; } - @Override - public boolean isSnapshot() - { - return checkSnapshot( delegate.toString() ); - } - @Override public int compareTo( Version o ) { From 446032e4eaead48a095377751c20f5f83c924a30 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 23 Sep 2022 16:52:15 +0200 Subject: [PATCH 95/98] Remove getBaseVersion and getId from Artifact --- .../java/org/apache/maven/api/Artifact.java | 22 ---------------- .../maven/internal/impl/DefaultArtifact.java | 7 ----- .../internal/impl/DefaultArtifactManager.java | 26 ++++++++++++++++--- 3 files changed, 22 insertions(+), 33 deletions(-) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index 65322716b872..58ab924af023 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -84,16 +84,6 @@ public interface Artifact @Nonnull Type getType(); - /** - * Gets the base version of this artifact, for example "1.0-SNAPSHOT". In contrast to the {@link #getVersion()}, the - * base version will always refer to the unresolved version. - * TODO: move this inside {@link Version} ? - * - * @return The base version, never {@code null}. - */ - @Nonnull - String getBaseVersion(); - /** * Determines whether this artifact uses a snapshot version. * @@ -111,16 +101,4 @@ public interface Artifact @Nonnull Optional getPath(); - /** - * Unique id identifying this artifact - */ - default String getId() - { - return getGroupId() - + ":" + getArtifactId() - + ":" + getExtension() - + ( getClassifier().isEmpty() ? "" : ":" + getClassifier() ) - + ":" + getBaseVersion(); - } - } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java index 8ab5ec173bf6..53cc338d3a4d 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -95,13 +95,6 @@ public String getClassifier() return artifact.getClassifier(); } - @Nonnull - @Override - public String getBaseVersion() - { - return artifact.getBaseVersion(); - } - @Override public boolean isSnapshot() { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java index 818719701d2f..6e9208b5b43e 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java @@ -53,10 +53,10 @@ public Optional getPath( @Nonnull Artifact artifact ) { if ( session.getMavenSession().getAllProjects() != null ) { - String id = artifact.getId(); + String id = id( artifact ); for ( MavenProject project : session.getMavenSession().getAllProjects() ) { - if ( id.equals( project.getArtifact().getId() ) && project.getArtifact().getFile() != null ) + if ( id.equals( id( project.getArtifact() ) ) && project.getArtifact().getFile() != null ) { return Optional.of( project.getArtifact().getFile().toPath() ); } @@ -71,10 +71,10 @@ public void setPath( @Nonnull Artifact artifact, Path path ) { if ( session.getMavenSession().getAllProjects() != null ) { - String id = artifact.getId(); + String id = id( artifact ); for ( MavenProject project : session.getMavenSession().getAllProjects() ) { - if ( id.equals( project.getArtifact().getId() ) ) + if ( id.equals( id( project.getArtifact() ) ) ) { project.getArtifact().setFile( path != null ? path.toFile() : null ); break; @@ -105,4 +105,22 @@ public void attachMetadata( @Nonnull Artifact artifact, @Nonnull Metadata metada metadatas.computeIfAbsent( artifact, a -> new CopyOnWriteArrayList<>() ).add( metadata ); } + private String id( org.apache.maven.artifact.Artifact artifact ) + { + return artifact.getGroupId() + + ":" + artifact.getArtifactId() + + ":" + artifact.getType() + + ( artifact.getClassifier().isEmpty() ? "" : ":" + artifact.getClassifier() ) + + ":" + artifact.getVersion(); + } + + private String id( Artifact artifact ) + { + return artifact.getGroupId() + + ":" + artifact.getArtifactId() + + ":" + artifact.getExtension() + + ( artifact.getClassifier().isEmpty() ? "" : ":" + artifact.getClassifier() ) + + ":" + artifact.getVersion(); + } + } From 8e2e0fb35080c42cebcb4aff7c65dc7250b82629 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 23 Sep 2022 16:53:50 +0200 Subject: [PATCH 96/98] Use asString instead of toString for Version and VersionRange --- .../main/java/org/apache/maven/api/Session.java | 1 + .../main/java/org/apache/maven/api/Version.java | 3 ++- .../java/org/apache/maven/api/VersionRange.java | 4 +++- .../internal/impl/DefaultVersionParser.java | 16 ++++++++++++++-- 4 files changed, 20 insertions(+), 4 deletions(-) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index 258d8be6c48a..b66dd20e0410 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -58,6 +58,7 @@ public interface Session @Nonnull SessionData getData(); + // TODO: investigate using Map or Map for all properties in the new API @Nonnull Properties getUserProperties(); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java index e84057bd4d72..bf75f6c1d232 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Version.java @@ -34,12 +34,13 @@ public interface Version extends Comparable { + // TODO: add access to the version information /** * Returns a string representation of this version. * @return the string representation of this version */ @Nonnull - String toString(); + String asString(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java index 398aab3d30b7..fb3e39b2f630 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/VersionRange.java @@ -31,6 +31,8 @@ public interface VersionRange { + // TODO: add access to the version information + /** * Determines whether the specified version is contained within this range. * @@ -44,5 +46,5 @@ public interface VersionRange * @return the string representation of this version range */ @Nonnull - String toString(); + String asString(); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java index b7e406fa3e39..03762c997877 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultVersionParser.java @@ -112,10 +112,16 @@ public int hashCode() } @Override - public String toString() + public String asString() { return delegate.toString(); } + + @Override + public String toString() + { + return asString(); + } } static class DefaultVersionRange implements VersionRange @@ -141,9 +147,15 @@ public boolean contains( Version version ) } @Override - public String toString() + public String asString() { return delegate.toString(); } + + @Override + public String toString() + { + return asString(); + } } } From 762125c871152789701f5cd3e1fbe15d026f8190 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Thu, 29 Sep 2022 16:08:22 +0200 Subject: [PATCH 97/98] Various enhancements to the API * Introduce a Lookup service to retrieve beans from the PlexusContainer * Improvements to the Node dependency graph * Add access to the parent and remote repositories from the project * Enhancements to better support Coordinate * Add ProjectManager#setProperty --- .../main/java/org/apache/maven/api/Node.java | 9 +- .../java/org/apache/maven/api/Project.java | 15 ++- .../org/apache/maven/api/ResolutionScope.java | 12 ++ .../java/org/apache/maven/api/Session.java | 14 +- .../maven/api/services/ArtifactResolver.java | 6 +- .../maven/api/services/CoordinateFactory.java | 33 +++++ .../services/DependencyCollectorRequest.java | 44 ++++-- .../maven/api/services/DependencyFactory.java | 8 +- .../services/DependencyFactoryRequest.java | 35 +++-- .../api/services/DependencyResolver.java | 50 +++++++ .../services/DependencyResolverRequest.java | 24 +++- .../org/apache/maven/api/services/Lookup.java | 38 ++++++ .../maven/api/services/LookupException.java | 50 +++++++ .../maven/api/services/ProjectBuilder.java | 16 +++ .../api/services/ProjectBuilderRequest.java | 32 ++++- .../maven/api/services/ProjectManager.java | 2 + .../maven/internal/impl/AbstractNode.java | 86 ++++++++++++ .../maven/internal/impl/AbstractSession.java | 35 ++++- .../internal/impl/DefaultArtifactManager.java | 3 +- .../impl/DefaultCoordinateFactory.java | 4 +- .../impl/DefaultDependencyCollector.java | 18 ++- .../impl/DefaultDependencyFactory.java | 2 +- .../maven/internal/impl/DefaultLookup.java | 91 +++++++++++++ .../maven/internal/impl/DefaultNode.java | 126 ++++++++++++++---- .../maven/internal/impl/DefaultProject.java | 20 +++ .../internal/impl/DefaultProjectBuilder.java | 10 ++ .../internal/impl/DefaultProjectManager.java | 6 + .../maven/internal/impl/DefaultSession.java | 5 + .../maven/internal/impl/WrapperNode.java | 88 ++++++++++++ 29 files changed, 800 insertions(+), 82 deletions(-) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/Lookup.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/AbstractNode.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLookup.java create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java index f79bf943bc90..6d8200071b09 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java @@ -60,7 +60,7 @@ public interface Node * @return repositories of this node */ @Nonnull - List getRemoteRepositories(); + List getRemoteRepositories(); /** * The repository where this artifact has been downloaded from. @@ -86,6 +86,13 @@ public interface Node */ Node filter( Predicate filter ); + /** + * Returns a string representation of this dependency node. + * + * @return the string representation + */ + String asString(); + /** * Obtain a Stream containing this node and all its descendant. * diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java index c2483080180c..4dcdfde7a610 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -19,13 +19,12 @@ * under the License. */ -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Nonnull; - import java.nio.file.Path; import java.util.List; import java.util.Optional; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Build; import org.apache.maven.api.model.Model; @@ -93,4 +92,14 @@ default String getId() } boolean isExecutionRoot(); + + @Nonnull + Optional getParent(); + + @Nonnull + List getRemoteProjectRepositories(); + + @Nonnull + List getRemotePluginRepositories(); + } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java index 26839de6927b..98d22fc6e381 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java @@ -72,6 +72,18 @@ public enum ResolutionScope private final String id; private final Set scopes; + public static ResolutionScope fromString( String id ) + { + for ( ResolutionScope scope : ResolutionScope.values() ) + { + if ( scope.id().equals( id ) ) + { + return scope; + } + } + throw new IllegalArgumentException( "Unknown resolution scope " + id ); + } + ResolutionScope( String id, Scope... scopes ) { this.id = id; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index b66dd20e0410..2abb9ac71516 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -202,7 +202,15 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri * * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed */ - Artifact resolveArtifact( Coordinate artifact ); + Artifact resolveArtifact( Coordinate coordinate ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Coordinate) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Artifact resolveArtifact( Artifact artifact ); /** * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} @@ -249,10 +257,10 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri /** * Shortcut for getService(DependencyFactory.class).create(...) - * @see org.apache.maven.api.services.DependencyFactory#create(Session, Artifact) + * @see org.apache.maven.api.services.DependencyFactory#create(Session, Coordinate) */ @Nonnull - Dependency createDependency( @Nonnull Artifact artifact ); + Dependency createDependency( @Nonnull Coordinate coordinate ); /** * Shortcut for getService(DependencyCollector.class).collect(...) diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java index 0b125ee0bc98..516734365407 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -45,16 +45,16 @@ public interface ArtifactResolver extends Service /** * @param session {@link Session} - * @param artifact {@link Artifact} + * @param coordinate {@link Artifact} * @return {@link ArtifactResolverResult} * @throws ArtifactResolverException in case of an error. * @throws IllegalArgumentException in case of parameter {@code buildingRequest} is {@code null} or * parameter {@code coordinate} is {@code null} or invalid. */ default ArtifactResolverResult resolve( Session session, - Coordinate artifact ) + Coordinate coordinate ) { - return resolve( ArtifactResolverRequest.build( session, artifact ) ); + return resolve( ArtifactResolverRequest.build( session, coordinate ) ); } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java index 0c56fe80857c..d2cbaa1444e7 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java @@ -19,11 +19,15 @@ * under the License. */ +import org.apache.maven.api.Artifact; import org.apache.maven.api.Coordinate; import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.ReportPlugin; /** * Service used to create {@link Coordinate} objects. @@ -58,4 +62,33 @@ default Coordinate create( @Nonnull Session session, String groupId, String arti return create( CoordinateFactoryRequest.build( session, groupId, artifactId, version, classifier, extension, type ) ); } + + @Nonnull + default Coordinate create( @Nonnull Session session, Dependency dependency ) + { + return create( CoordinateFactoryRequest.build( session, + dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), null ) ); + } + + @Nonnull + default Coordinate create( @Nonnull Session session, Artifact artifact ) + { + return create( CoordinateFactoryRequest.build( session, + artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion().asString(), + artifact.getClassifier(), artifact.getExtension(), artifact.getType().getName() ) ); + } + + @Nonnull + default Coordinate create( @Nonnull Session session, Plugin plugin ) + { + return create( CoordinateFactoryRequest.build( session, + plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(), null ) ); + } + + @Nonnull + default Coordinate create( @Nonnull Session session, ReportPlugin reportPlugin ) + { + return create( CoordinateFactoryRequest.build( session, + reportPlugin.getGroupId(), reportPlugin.getArtifactId(), reportPlugin.getVersion(), null ) ); + } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java index 3bc8dadfbcb0..7309e73b7f45 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java @@ -19,20 +19,19 @@ * under the License. */ -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Immutable; -import org.apache.maven.api.annotations.Nonnull; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Optional; +import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; import org.apache.maven.api.Project; import org.apache.maven.api.Session; -import org.apache.maven.api.Artifact; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.NotThreadSafe; import org.apache.maven.api.annotations.Nullable; @@ -68,12 +67,14 @@ public interface DependencyCollectorRequest @Nonnull Collection getManagedDependencies(); + boolean getVerbose(); + @Nonnull static DependencyCollectorRequest build( @Nonnull Session session, Artifact root ) { return builder() .session( nonNull( session, "session can not be null" ) ) - .root( session.createDependency( nonNull( root, "root can not be null" ) ) ) + .rootArtifact( nonNull( root, "root can not be null" ) ) .build(); } @@ -93,7 +94,7 @@ static DependencyCollectorRequest build( @Nonnull Session session, @Nonnull Proj nonNull( project, "project can not be null" ); return builder() .session( session ) - .root( session.createDependency( project.getArtifact() ) ) + .rootArtifact( project.getArtifact() ) .dependencies( project.getDependencies() ) .managedDependencies( project.getManagedDependencies() ) .build(); @@ -114,6 +115,7 @@ class DependencyCollectorRequestBuilder Dependency root; List dependencies = Collections.emptyList(); List managedDependencies = Collections.emptyList(); + boolean verbose; @Nonnull public DependencyCollectorRequestBuilder session( @Nonnull Session session ) @@ -223,6 +225,19 @@ public DependencyCollectorRequestBuilder managedDependency( @Nullable Dependency return this; } + /** + * Specifies that the collection should be verbose. + * + * @param verbose whether the collection should be verbose or not. + * @return This request for chaining, never {@code null}. + */ + @Nonnull + public DependencyCollectorRequestBuilder verbose( boolean verbose ) + { + this.verbose = verbose; + return this; + } + @Nonnull public DependencyCollectorRequest build() { @@ -231,7 +246,8 @@ public DependencyCollectorRequest build() rootArtifact, root, dependencies, - managedDependencies ); + managedDependencies, + verbose ); } static class DefaultDependencyCollectorRequest extends BaseRequest @@ -241,6 +257,7 @@ static class DefaultDependencyCollectorRequest extends BaseRequest private final Dependency root; private final Collection dependencies; private final Collection managedDependencies; + private final boolean verbose; /** @@ -255,14 +272,15 @@ static class DefaultDependencyCollectorRequest extends BaseRequest @Nullable Artifact rootArtifact, @Nullable Dependency root, @Nonnull Collection dependencies, - @Nonnull Collection managedDependencies ) + @Nonnull Collection managedDependencies, + boolean verbose ) { super( session ); this.rootArtifact = rootArtifact; this.root = root; this.dependencies = unmodifiable( dependencies ); this.managedDependencies = unmodifiable( managedDependencies ); - + this.verbose = verbose; } @Nonnull @@ -293,6 +311,12 @@ public Collection getManagedDependencies() return managedDependencies; } + @Override + public boolean getVerbose() + { + return verbose; + } + @Nonnull @Override public String toString() diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java index d33fa7cb53a6..be4c39bc7c63 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java @@ -19,10 +19,10 @@ * under the License. */ +import org.apache.maven.api.Coordinate; +import org.apache.maven.api.Dependency; import org.apache.maven.api.Service; import org.apache.maven.api.Session; -import org.apache.maven.api.Artifact; -import org.apache.maven.api.Dependency; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; @@ -47,8 +47,8 @@ public interface DependencyFactory extends Service Dependency create( @Nonnull DependencyFactoryRequest request ); @Nonnull - default Dependency create( @Nonnull Session session, @Nonnull Artifact artifact ) + default Dependency create( @Nonnull Session session, @Nonnull Coordinate coordinate ) { - return create( DependencyFactoryRequest.build( session, artifact ) ); + return create( DependencyFactoryRequest.build( session, coordinate ) ); } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java index 4f62e8985aa9..4dd5ac9ce18e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java @@ -19,17 +19,16 @@ * under the License. */ -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Immutable; -import org.apache.maven.api.annotations.Nonnull; - import java.util.ArrayList; import java.util.Collection; import java.util.Collections; -import org.apache.maven.api.Session; -import org.apache.maven.api.Artifact; +import org.apache.maven.api.Coordinate; import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.NotThreadSafe; /** @@ -44,7 +43,7 @@ public interface DependencyFactoryRequest @Nonnull Session getSession(); - Artifact getArtifact(); + Coordinate getCoordinate(); String getScope(); @@ -53,11 +52,11 @@ public interface DependencyFactoryRequest @Nonnull Collection getExclusions(); - static DependencyFactoryRequest build( Session session, Artifact artifact ) + static DependencyFactoryRequest build( Session session, Coordinate coordinate ) { return builder() .session( session ) - .artifact( artifact ) + .coordinate( coordinate ) .build(); } @@ -70,7 +69,7 @@ static DependencyFactoryRequestBuilder builder() class DependencyFactoryRequestBuilder { private Session session; - private Artifact artifact; + private Coordinate coordinate; private String scope; private boolean optional; private Collection exclusions = Collections.emptyList(); @@ -81,9 +80,9 @@ public DependencyFactoryRequestBuilder session( Session session ) return this; } - public DependencyFactoryRequestBuilder artifact( Artifact artifact ) + public DependencyFactoryRequestBuilder coordinate( Coordinate coordinate ) { - this.artifact = artifact; + this.coordinate = coordinate; return this; } @@ -127,30 +126,30 @@ public DependencyFactoryRequestBuilder exclusion( Exclusion exclusion ) public DependencyFactoryRequest build() { - return new DefaultDependencyFactoryRequest( session, artifact, scope, optional, exclusions ); + return new DefaultDependencyFactoryRequest( session, coordinate, scope, optional, exclusions ); } private static class DefaultDependencyFactoryRequest extends BaseRequest implements DependencyFactoryRequest { - private final Artifact artifact; + private final Coordinate coordinate; private final String scope; private final boolean optional; private final Collection exclusions; - private DefaultDependencyFactoryRequest( @Nonnull Session session, Artifact artifact, String scope, + private DefaultDependencyFactoryRequest( @Nonnull Session session, Coordinate coordinate, String scope, boolean optional, Collection exclusions ) { super( session ); - this.artifact = artifact; + this.coordinate = coordinate; this.scope = scope; this.optional = optional; this.exclusions = exclusions; } @Override - public Artifact getArtifact() + public Coordinate getCoordinate() { - return artifact; + return coordinate; } @Override diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java index 4f705fb2948d..d97856710177 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java @@ -21,6 +21,7 @@ import java.util.function.Predicate; +import org.apache.maven.api.Coordinate; import org.apache.maven.api.Service; import org.apache.maven.api.Session; import org.apache.maven.api.Dependency; @@ -49,6 +50,55 @@ public interface DependencyResolver extends Service */ DependencyResolverResult resolve( DependencyResolverRequest request ); + /** + * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. + * + * @param session The {@link Session}, must not be {@code null}. + * @param coordinate {@link Coordinate} + * @return the resolved dependencies. + * @throws DependencyResolverException in case of an error. + * @throws IllegalArgumentException if {@code request} is null or invalid + */ + @Nonnull + default DependencyResolverResult resolve( @Nonnull Session session, + @Nonnull Coordinate coordinate ) + { + return resolve( session, session.createDependency( coordinate ) ); + } + + /** + * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. + * + * @param session The {@link Session}, must not be {@code null}. + * @param coordinate {@link Coordinate} + * @return the resolved dependencies. + * @throws DependencyResolverException in case of an error. + * @throws IllegalArgumentException if {@code request} is null or invalid + */ + @Nonnull + default DependencyResolverResult resolve( @Nonnull Session session, + @Nonnull Coordinate coordinate, + @Nullable Predicate filter ) + { + return resolve( session, session.createDependency( coordinate ), filter ); + } + + /** + * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. + * + * @param session The {@link Session}, must not be {@code null}. + * @param root {@link Dependency} + * @return the resolved dependencies. + * @throws DependencyResolverException in case of an error. + * @throws IllegalArgumentException if {@code request} is null or invalid + */ + @Nonnull + default DependencyResolverResult resolve( @Nonnull Session session, + @Nonnull Dependency root ) + { + return resolve( session, root, null ); + } + /** * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. * diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java index 7485bfa35327..79bce874c0f3 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java @@ -107,7 +107,7 @@ static DependencyResolverRequest build( @Nonnull Session session, nonNull( project, "project can not be null" ); return builder() .session( session ) - .root( session.createDependency( project.getArtifact() ) ) + .rootArtifact( project.getArtifact() ) .dependencies( project.getDependencies() ) .managedDependencies( project.getManagedDependencies() ) .filter( filter ) @@ -129,6 +129,7 @@ class DependencyResolverRequestBuilder List dependencies = Collections.emptyList(); List managedDependencies = Collections.emptyList(); Predicate filter; + boolean verbose; @Nonnull public DependencyResolverRequestBuilder session( @Nonnull Session session ) @@ -245,6 +246,13 @@ public DependencyResolverRequestBuilder filter( @Nullable Predicate filter return this; } + @Nonnull + public DependencyResolverRequestBuilder verbose( boolean verbose ) + { + this.verbose = verbose; + return this; + } + @Nonnull public DependencyResolverRequest build() { @@ -254,7 +262,8 @@ public DependencyResolverRequest build() root, dependencies, managedDependencies, - filter ); + filter, + verbose ); } private static class DefaultDependencyResolverRequest extends BaseRequest @@ -265,6 +274,7 @@ private static class DefaultDependencyResolverRequest extends BaseRequest private final Collection dependencies; private final Collection managedDependencies; private final Predicate filter; + private final boolean verbose; /** @@ -280,7 +290,8 @@ private static class DefaultDependencyResolverRequest extends BaseRequest @Nullable Dependency root, @Nullable Collection dependencies, @Nullable Collection managedDependencies, - @Nullable Predicate filter ) + @Nullable Predicate filter, + boolean verbose ) { super( session ); this.rootArtifact = rootArtifact; @@ -288,6 +299,7 @@ private static class DefaultDependencyResolverRequest extends BaseRequest this.dependencies = unmodifiable( dependencies ); this.managedDependencies = unmodifiable( managedDependencies ); this.filter = filter; + this.verbose = verbose; } @Nonnull @@ -325,6 +337,12 @@ public Optional> getFilter() return Optional.ofNullable( filter ); } + @Override + public boolean getVerbose() + { + return verbose; + } + @Override public String toString() { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/Lookup.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Lookup.java new file mode 100644 index 000000000000..93e24994edbb --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/Lookup.java @@ -0,0 +1,38 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.Service; + +public interface Lookup extends Service +{ + + T lookup( Class type ); + + T lookup( Class type, String name ); + + List lookupList( Class type ); + + Map lookupMap( Class type ); + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java new file mode 100644 index 000000000000..d88549112e87 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/LookupException.java @@ -0,0 +1,50 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.annotations.Experimental; + +/** + * The Exception class throw by the {@link Lookup} service. + * + * @since 4.0 + */ +@Experimental +public class LookupException + extends MavenException +{ + /** + * @param message The message to give. + * @param e The {@link Exception}. + */ + public LookupException( String message, Exception e ) + { + super( message, e ); + } + + /** + * @param e The {@link Exception}. + */ + public LookupException( Exception e ) + { + super( e ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java index 1c0c50813fc1..986d8084b855 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Coordinate; import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; @@ -91,4 +92,19 @@ default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Artifact return build( ProjectBuilderRequest.build( session, artifact ) ); } + /** + * Creates a {@link org.apache.maven.api.Project} from a coordinate. + * + * @param session The {@link Session}, must not be {@code null}. + * @param coordinate The {@link Coordinate}, must not be {@code null}. + * @throws ProjectBuilderException if the project can not be created + * @throws IllegalArgumentException if an argument is {@code null} or invalid + * @see #build(ProjectBuilderRequest) + */ + @Nonnull + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Coordinate coordinate ) + { + return build( ProjectBuilderRequest.build( session, coordinate ) ); + } + } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java index 3e38050aa310..10dd3c36eff7 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Coordinate; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; @@ -56,6 +57,9 @@ public interface ProjectBuilderRequest @Nonnull Optional getArtifact(); + @Nonnull + Optional getCoordinate(); + boolean isAllowStubModel(); boolean isRecursive(); @@ -91,6 +95,15 @@ static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Artifact .build(); } + @Nonnull + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Coordinate coordinate ) + { + return builder() + .session( nonNull( session, "session can not be null" ) ) + .coordinate( nonNull( coordinate, "coordinate can not be null" ) ) + .build(); + } + @Nonnull static ProjectBuilderRequestBuilder builder() { @@ -104,6 +117,7 @@ class ProjectBuilderRequestBuilder Path path; ProjectBuilderSource source; Artifact artifact; + Coordinate coordinate; boolean allowStubModel; boolean recursive; boolean processPlugins = true; @@ -133,6 +147,12 @@ public ProjectBuilderRequestBuilder artifact( Artifact artifact ) return this; } + public ProjectBuilderRequestBuilder coordinate( Coordinate coordinate ) + { + this.coordinate = coordinate; + return this; + } + public ProjectBuilderRequestBuilder processPlugins( boolean processPlugins ) { this.processPlugins = processPlugins; @@ -147,7 +167,7 @@ public ProjectBuilderRequestBuilder resolveDependencies( boolean resolveDependen public ProjectBuilderRequest build() { - return new DefaultProjectBuilderRequest( session, path, source, artifact, + return new DefaultProjectBuilderRequest( session, path, source, artifact, coordinate, allowStubModel, recursive, processPlugins, resolveDependencies ); } @@ -157,6 +177,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest private final Path path; private final ProjectBuilderSource source; private final Artifact artifact; + private final Coordinate coordinate; private final boolean allowStubModel; private final boolean recursive; private final boolean processPlugins; @@ -167,6 +188,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest @Nullable Path path, @Nullable ProjectBuilderSource source, @Nullable Artifact artifact, + @Nullable Coordinate coordinate, boolean allowStubModel, boolean recursive, boolean processPlugins, @@ -176,6 +198,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest this.path = path; this.source = source; this.artifact = artifact; + this.coordinate = coordinate; this.allowStubModel = allowStubModel; this.recursive = recursive; this.processPlugins = processPlugins; @@ -203,6 +226,13 @@ public Optional getArtifact() return Optional.ofNullable( artifact ); } + @Nonnull + @Override + public Optional getCoordinate() + { + return Optional.ofNullable( coordinate ); + } + @Override public boolean isAllowStubModel() { diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java index e649d42f5478..a908bf19aca9 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectManager.java @@ -88,4 +88,6 @@ default void attachArtifact( Session session, Project project, String type, Path Node getCollectedDependencies( Project project, ResolutionScope scope ); + void setProperty( Project project, String key, String value ); + } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractNode.java new file mode 100644 index 000000000000..199d7222167e --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractNode.java @@ -0,0 +1,86 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Collections; +import java.util.List; +import java.util.function.Predicate; +import java.util.stream.Collectors; + +import org.apache.maven.api.Node; +import org.apache.maven.api.NodeVisitor; +import org.eclipse.aether.artifact.Artifact; +import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.graph.DependencyNode; + +public abstract class AbstractNode implements Node +{ + + abstract org.eclipse.aether.graph.DependencyNode getDependencyNode(); + + @Override + public boolean accept( NodeVisitor visitor ) + { + if ( visitor.enter( this ) ) + { + for ( Node child : getChildren() ) + { + if ( !child.accept( visitor ) ) + { + break; + } + } + } + return visitor.leave( this ); + } + + @Override + public Node filter( Predicate filter ) + { + List children = getChildren().stream().filter( filter ) + .map( n -> n.filter( filter ) ) + .collect( Collectors.toList() ); + return new WrapperNode( this, Collections.unmodifiableList( children ) ); + } + + @Override + public String asString() + { + StringBuilder sb = new StringBuilder(); + + DependencyNode node = getDependencyNode(); + Artifact artifact = node.getArtifact(); + sb.append( artifact ); + + Dependency dependency = node.getDependency(); + if ( dependency != null ) + { + sb.append( ":" ).append( dependency.getScope() ); + } + + return sb.toString(); + } + + @Override + public String toString() + { + return getDependencyNode().toString(); + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java index 2c47b827da72..85f262cc85e0 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java @@ -91,7 +91,12 @@ public RemoteRepository getRemoteRepository( org.eclipse.aether.repository.Remot public Node getNode( org.eclipse.aether.graph.DependencyNode node ) { - return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n ) ); + return getNode( node, false ); + } + + public Node getNode( org.eclipse.aether.graph.DependencyNode node, boolean verbose ) + { + return allNodes.computeIfAbsent( node, n -> new DefaultNode( this, n, verbose ) ); } @Nonnull @@ -200,6 +205,10 @@ public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact ) public org.eclipse.aether.artifact.Artifact toArtifact( Coordinate coord ) { + if ( coord instanceof DefaultCoordinate ) + { + return ( ( DefaultCoordinate ) coord ).getCoordinate(); + } return new org.eclipse.aether.artifact.DefaultArtifact( coord.getGroupId(), coord.getArtifactId(), @@ -355,13 +364,27 @@ public Artifact createArtifact( String groupId, String artifactId, String versio * @see ArtifactResolver#resolve(Session, Coordinate) */ @Override - public Artifact resolveArtifact( Coordinate artifact ) + public Artifact resolveArtifact( Coordinate coordinate ) { return getService( ArtifactResolver.class ) - .resolve( this, artifact ) + .resolve( this, coordinate ) .getArtifact(); } + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Coordinate) + */ + @Override + public Artifact resolveArtifact( Artifact artifact ) + { + Coordinate coordinate = getService( CoordinateFactory.class ) + .create( this, artifact ); + return resolveArtifact( coordinate ); + } + /** * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} * @@ -440,14 +463,14 @@ public boolean isVersionSnapshot( @Nonnull String version ) /** * Shortcut for getService(DependencyFactory.class).create(...) * - * @see DependencyFactory#create(Session, Artifact) + * @see DependencyFactory#create(Session, Coordinate) */ @Nonnull @Override - public Dependency createDependency( @Nonnull Artifact artifact ) + public Dependency createDependency( @Nonnull Coordinate coordinate ) { return getService( DependencyFactory.class ) - .create( this, artifact ); + .create( this, coordinate ); } /** diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java index 6e9208b5b43e..a54ea574089c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java @@ -110,7 +110,8 @@ private String id( org.apache.maven.artifact.Artifact artifact ) return artifact.getGroupId() + ":" + artifact.getArtifactId() + ":" + artifact.getType() - + ( artifact.getClassifier().isEmpty() ? "" : ":" + artifact.getClassifier() ) + + ( artifact.getClassifier() == null || artifact.getClassifier().isEmpty() + ? "" : ":" + artifact.getClassifier() ) + ":" + artifact.getVersion(); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java index 21e451819b32..eca9012b9582 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java @@ -46,9 +46,9 @@ public Coordinate create( @Nonnull CoordinateFactoryRequest request ) type = session.getSession().getArtifactTypeRegistry().get( request.getType() ); } String classifier = StringUtils.isNotEmpty( request.getClassifier() ) - ? request.getClassifier() : type != null ? type.getClassifier() : null; + ? request.getClassifier() : type != null ? type.getClassifier() : ""; String extension = StringUtils.isNotEmpty( request.getExtension() ) - ? request.getExtension() : type != null ? type.getExtension() : null; + ? request.getExtension() : type != null ? type.getExtension() : ""; return new DefaultCoordinate( session, new org.eclipse.aether.artifact.DefaultArtifact( diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java index 7edd4f7a53ee..83ea3732a60d 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCollector.java @@ -30,12 +30,16 @@ import org.apache.maven.api.services.DependencyCollectorException; import org.apache.maven.api.services.DependencyCollectorRequest; import org.apache.maven.api.services.DependencyCollectorResult; +import org.eclipse.aether.DefaultRepositorySystemSession; import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.RepositorySystemSession; import org.eclipse.aether.artifact.Artifact; import org.eclipse.aether.collection.CollectRequest; import org.eclipse.aether.collection.CollectResult; import org.eclipse.aether.collection.DependencyCollectionException; import org.eclipse.aether.graph.Dependency; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.transformer.ConflictResolver; import static org.apache.maven.internal.impl.Utils.cast; import static org.apache.maven.internal.impl.Utils.nonNull; @@ -65,15 +69,23 @@ public DependencyCollectorResult collect( @Nonnull DependencyCollectorRequest re Dependency root = request.getRoot().map( session::toDependency ).orElse( null ); CollectRequest collectRequest = new CollectRequest() .setRootArtifact( rootArtifact ) - .setRoot( root != null ? root : new Dependency( rootArtifact, null ) ) + .setRoot( root ) .setDependencies( session.toDependencies( request.getDependencies() ) ) .setManagedDependencies( session.toDependencies( request.getManagedDependencies() ) ) .setRepositories( session.toRepositories( session.getRemoteRepositories() ) ); + RepositorySystemSession systemSession = session.getSession(); + if ( request.getVerbose() ) + { + systemSession = new DefaultRepositorySystemSession( systemSession ) + .setConfigProperty( ConflictResolver.CONFIG_PROP_VERBOSE, true ) + .setConfigProperty( DependencyManagerUtils.CONFIG_PROP_VERBOSE, true ); + } + try { final CollectResult - result = repositorySystem.collectDependencies( session.getSession(), collectRequest ); + result = repositorySystem.collectDependencies( systemSession, collectRequest ); return new DependencyCollectorResult() { @Override @@ -85,7 +97,7 @@ public List getExceptions() @Override public Node getRoot() { - return session.getNode( result.getRoot() ); + return session.getNode( result.getRoot(), request.getVerbose() ); } }; } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java index 62327ed70634..676cbea03d62 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java @@ -47,7 +47,7 @@ public Dependency create( @Nonnull DependencyFactoryRequest request ) return new DefaultDependency( session, new org.eclipse.aether.graph.Dependency( - session.toArtifact( request.getArtifact() ), + session.toArtifact( request.getCoordinate() ), request.getScope(), request.isOptional(), request.getExclusions().stream().map( this::toExclusion ).collect( Collectors.toList() ) ) ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLookup.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLookup.java new file mode 100644 index 000000000000..9df503cd7d8f --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultLookup.java @@ -0,0 +1,91 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.List; +import java.util.Map; + +import org.apache.maven.api.services.Lookup; +import org.apache.maven.api.services.LookupException; +import org.codehaus.plexus.PlexusContainer; +import org.codehaus.plexus.component.repository.exception.ComponentLookupException; + +public class DefaultLookup implements Lookup +{ + + private final PlexusContainer container; + + public DefaultLookup( PlexusContainer container ) + { + this.container = container; + } + + @Override + public T lookup( Class type ) + { + try + { + return container.lookup( type ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } + + @Override + public T lookup( Class type, String name ) + { + try + { + return container.lookup( type, name ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } + + @Override + public List lookupList( Class type ) + { + try + { + return container.lookupList( type ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } + + @Override + public Map lookupMap( Class type ) + { + try + { + return container.lookupMap( type ); + } + catch ( ComponentLookupException e ) + { + throw new LookupException( e ); + } + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java index 04c3d5527803..8da774390e97 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java @@ -19,51 +19,62 @@ * under the License. */ +import java.util.ArrayList; import java.util.List; +import java.util.Objects; import java.util.Optional; -import java.util.function.Predicate; import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; import org.apache.maven.api.Node; -import org.apache.maven.api.NodeVisitor; import org.apache.maven.api.RemoteRepository; -import org.apache.maven.api.Repository; import org.apache.maven.api.annotations.Nonnull; +import org.eclipse.aether.graph.DependencyNode; +import org.eclipse.aether.util.graph.manager.DependencyManagerUtils; +import org.eclipse.aether.util.graph.transformer.ConflictResolver; -public class DefaultNode implements Node +public class DefaultNode extends AbstractNode { - private final @Nonnull AbstractSession session; - private final @Nonnull org.eclipse.aether.graph.DependencyNode node; + protected final @Nonnull AbstractSession session; + protected final @Nonnull org.eclipse.aether.graph.DependencyNode node; + protected final boolean verbose; public DefaultNode( @Nonnull AbstractSession session, - @Nonnull org.eclipse.aether.graph.DependencyNode node ) + @Nonnull org.eclipse.aether.graph.DependencyNode node, + boolean verbose ) { this.session = session; this.node = node; + this.verbose = verbose; + } + + @Override + DependencyNode getDependencyNode() + { + return node; } @Override public Artifact getArtifact() { - return session.getArtifact( node.getArtifact() ); + return node.getArtifact() != null ? session.getArtifact( node.getArtifact() ) : null; } @Override public Dependency getDependency() { - return session.getDependency( node.getDependency() ); + return node.getDependency() != null ? session.getDependency( node.getDependency() ) : null; } @Override public List getChildren() { - return new MappedList<>( node.getChildren(), session::getNode ); + return new MappedList<>( node.getChildren(), n -> session.getNode( n, verbose ) ); } @Override - public List getRemoteRepositories() + public List getRemoteRepositories() { return new MappedList<>( node.getRepositories(), session::getRemoteRepository ); } @@ -76,25 +87,94 @@ public Optional getRepository() } @Override - public boolean accept( NodeVisitor visitor ) + public String asString() { - if ( visitor.enter( this ) ) + String nodeString = super.asString(); + + if ( !verbose ) + { + return nodeString; + } + + org.eclipse.aether.graph.DependencyNode node = getDependencyNode(); + + List details = new ArrayList<>(); + + org.eclipse.aether.graph.DependencyNode winner = + (org.eclipse.aether.graph.DependencyNode) node.getData().get( ConflictResolver.NODE_DATA_WINNER ); + String winnerVersion = winner != null ? winner.getArtifact().getBaseVersion() : null; + boolean included = ( winnerVersion == null ); + + String preManagedVersion = DependencyManagerUtils.getPremanagedVersion( node ); + if ( preManagedVersion != null ) { - for ( Node child : getChildren() ) + details.add( "version managed from " + preManagedVersion ); + } + + String preManagedScope = DependencyManagerUtils.getPremanagedScope( node ); + if ( preManagedScope != null ) + { + details.add( "scope managed from " + preManagedScope ); + } + + String originalScope = (String) node.getData().get( ConflictResolver.NODE_DATA_ORIGINAL_SCOPE ); + if ( originalScope != null && !originalScope.equals( node.getDependency().getScope() ) ) + { + details.add( "scope updated from " + originalScope ); + } + + if ( !included ) + { + if ( Objects.equals( winnerVersion, node.getArtifact().getVersion() ) ) { - if ( !child.accept( visitor ) ) - { - break; - } + details.add( "omitted for duplicate" ); } + else + { + details.add( "omitted for conflict with " + winnerVersion ); + } + } + + StringBuilder buffer = new StringBuilder(); + if ( included ) + { + buffer.append( nodeString ); + if ( !details.isEmpty() ) + { + buffer.append( " (" ); + join( buffer, details, "; " ); + buffer.append( ")" ); + } + } + else + { + buffer.append( "(" ); + buffer.append( nodeString ); + if ( !details.isEmpty() ) + { + buffer.append( " - " ); + join( buffer, details, "; " ); + } + buffer.append( ")" ); } - return visitor.leave( this ); + return buffer.toString(); } - @Override - public Node filter( Predicate filter ) + private static void join( StringBuilder buffer, List details, String separator ) { - // TODO - throw new UnsupportedOperationException( "Not implemented yet" ); + boolean first = true; + for ( String detail : details ) + { + if ( first ) + { + first = false; + } + else + { + buffer.append( separator ); + } + buffer.append( detail ); + } } + } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java index 3c918b28c6f3..05a22b7c774c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.RemoteRepository; import org.apache.maven.api.Scope; import org.apache.maven.api.Type; import org.apache.maven.api.VersionRange; @@ -144,6 +145,25 @@ public boolean isExecutionRoot() return project.isExecutionRoot(); } + @Override + public Optional getParent() + { + MavenProject parent = project.getParent(); + return parent != null ? Optional.of( session.getProject( parent ) ) : Optional.empty(); + } + + @Override + public List getRemoteProjectRepositories() + { + return new MappedList<>( project.getRemoteProjectRepositories(), session::getRemoteRepository ); + } + + @Override + public List getRemotePluginRepositories() + { + return new MappedList<>( project.getRemotePluginRepositories(), session::getRemoteRepository ); + } + @Nonnull private Dependency toDependency( org.apache.maven.api.model.Dependency dependency ) { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java index 25e39ef40f2c..73e6a3a5311b 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.Coordinate; import org.apache.maven.api.annotations.Nonnull; import javax.inject.Inject; @@ -36,6 +37,7 @@ import org.apache.maven.api.Node; import org.apache.maven.api.Project; import org.apache.maven.api.services.ProjectBuilderProblemSeverity; +import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.building.ModelProblem; import org.apache.maven.model.building.ModelSource; @@ -111,6 +113,14 @@ else if ( request.getArtifact().isPresent() ) org.apache.maven.artifact.Artifact artifact = RepositoryUtils.toArtifact( aetherArtifact ); res = builder.build( artifact, request.isAllowStubModel(), req ); } + else if ( request.getCoordinate().isPresent() ) + { + Coordinate c = request.getCoordinate().get(); + org.apache.maven.artifact.Artifact artifact = new DefaultArtifact( + c.getGroupId(), c.getArtifactId(), c.getVersion().asString(), null, + c.getType().getName(), c.getClassifier(), null ); + res = builder.build( artifact, request.isAllowStubModel(), req ); + } else { throw new IllegalArgumentException( "Invalid request" ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java index 3626303106b5..4a5e62218180 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectManager.java @@ -158,6 +158,12 @@ public Node getCollectedDependencies( Project project, ResolutionScope scope ) throw new UnsupportedOperationException( "Not implemented yet" ); } + @Override + public void setProperty( Project project, String key, String value ) + { + getMavenProject( project ).getProperties().setProperty( key, value ); + } + private MavenProject getMavenProject( Project project ) { return ( ( DefaultProject ) project ).getProject(); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index 749d1f1ad4a0..a223e854663b 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -51,6 +51,7 @@ import org.apache.maven.api.services.DependencyFactory; import org.apache.maven.api.services.DependencyResolver; import org.apache.maven.api.services.LocalRepositoryManager; +import org.apache.maven.api.services.Lookup; import org.apache.maven.api.services.MavenException; import org.apache.maven.api.services.MessageBuilderFactory; import org.apache.maven.api.services.ProjectBuilder; @@ -383,6 +384,10 @@ else if ( clazz == TypeRegistry.class ) { return (T) new DefaultTypeRegistry( artifactHandlerManager ); } + else if ( clazz == Lookup.class ) + { + return (T) new DefaultLookup( container ); + } throw new NoSuchElementException( clazz.getName() ); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java new file mode 100644 index 000000000000..dd0e91abaa19 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java @@ -0,0 +1,88 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.List; +import java.util.Optional; + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Node; +import org.apache.maven.api.RemoteRepository; +import org.apache.maven.api.annotations.Nonnull; +import org.eclipse.aether.graph.DependencyNode; + +class WrapperNode extends AbstractNode +{ + protected final Node delegate; + protected final List children; + + WrapperNode( Node delegate, List children ) + { + this.delegate = delegate; + this.children = children; + } + + @Override + DependencyNode getDependencyNode() + { + return Utils.cast( AbstractNode.class, delegate, + "delegate is not an instance of AbstractNode" ).getDependencyNode(); + } + + @Override + public List getChildren() + { + return children; + } + + @Override + public Artifact getArtifact() + { + return delegate.getArtifact(); + } + + @Override + public Dependency getDependency() + { + return delegate.getDependency(); + } + + @Override + @Nonnull + public List getRemoteRepositories() + { + return delegate.getRemoteRepositories(); + } + + @Override + @Nonnull + public Optional getRepository() + { + return delegate.getRepository(); + } + + @Override + @Nonnull + public String asString() + { + return delegate.asString(); + } +} From d2408f446b89c06180f92a7905df2840e6b088a1 Mon Sep 17 00:00:00 2001 From: Guillaume Nodet Date: Fri, 30 Sep 2022 13:28:04 +0200 Subject: [PATCH 98/98] Introduce better coordinates, remove Artifact.getPath, move Artifact.getType to Dependency --- .../java/org/apache/maven/api/Artifact.java | 47 +-- ...oordinate.java => ArtifactCoordinate.java} | 10 +- .../java/org/apache/maven/api/Dependency.java | 34 +- ...rResult.java => DependencyCoordinate.java} | 33 +- .../java/org/apache/maven/api/Exclusion.java | 2 +- .../main/java/org/apache/maven/api/Node.java | 4 - .../java/org/apache/maven/api/Project.java | 4 +- .../org/apache/maven/api/ResolutionScope.java | 21 +- .../java/org/apache/maven/api/Session.java | 80 ++-- .../services/ArtifactCoordinateFactory.java | 71 ++++ ... => ArtifactCoordinateFactoryRequest.java} | 51 ++- .../maven/api/services/ArtifactResolver.java | 11 +- .../api/services/ArtifactResolverRequest.java | 28 +- .../api/services/ArtifactResolverResult.java | 7 +- .../maven/api/services/CoordinateFactory.java | 94 ----- .../api/services/DependencyCollector.java | 6 +- .../services/DependencyCollectorRequest.java | 49 +-- .../services/DependencyCoordinateFactory.java | 89 +++++ .../DependencyCoordinateFactoryRequest.java | 292 +++++++++++++++ .../maven/api/services/DependencyFactory.java | 54 --- .../services/DependencyFactoryRequest.java | 176 --------- .../api/services/DependencyResolver.java | 139 ------- .../services/DependencyResolverException.java | 59 --- .../services/DependencyResolverRequest.java | 354 ------------------ .../maven/api/services/ProjectBuilder.java | 6 +- .../api/services/ProjectBuilderRequest.java | 16 +- .../api/services/ProjectBuilderResult.java | 2 +- .../maven/internal/impl/AbstractSession.java | 132 ++++--- .../maven/internal/impl/DefaultArtifact.java | 56 ++- ...te.java => DefaultArtifactCoordinate.java} | 25 +- ... => DefaultArtifactCoordinateFactory.java} | 12 +- .../internal/impl/DefaultArtifactManager.java | 11 +- .../impl/DefaultArtifactResolver.java | 29 +- .../internal/impl/DefaultDependency.java | 69 ++-- .../impl/DefaultDependencyCoordinate.java | 132 +++++++ ...> DefaultDependencyCoordinateFactory.java} | 27 +- .../impl/DefaultDependencyResolver.java | 107 ------ .../maven/internal/impl/DefaultNode.java | 7 - .../maven/internal/impl/DefaultProject.java | 10 +- .../internal/impl/DefaultProjectBuilder.java | 40 +- .../maven/internal/impl/DefaultSession.java | 135 ++----- .../maven/internal/impl/WrapperNode.java | 7 - .../AbstractCoreMavenComponentTestCase.java | 4 +- .../apache/maven/internal/impl/TestApi.java | 16 +- 44 files changed, 1104 insertions(+), 1454 deletions(-) rename api/maven-api-core/src/main/java/org/apache/maven/api/{Coordinate.java => ArtifactCoordinate.java} (94%) rename api/maven-api-core/src/main/java/org/apache/maven/api/{services/DependencyResolverResult.java => DependencyCoordinate.java} (60%) create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactory.java rename api/maven-api-core/src/main/java/org/apache/maven/api/services/{CoordinateFactoryRequest.java => ArtifactCoordinateFactoryRequest.java} (70%) delete mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactory.java create mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactoryRequest.java delete mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java delete mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java delete mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java delete mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java delete mode 100644 api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java rename maven-core/src/main/java/org/apache/maven/internal/impl/{DefaultCoordinate.java => DefaultArtifactCoordinate.java} (78%) rename maven-core/src/main/java/org/apache/maven/internal/impl/{DefaultCoordinateFactory.java => DefaultArtifactCoordinateFactory.java} (84%) create mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinate.java rename maven-core/src/main/java/org/apache/maven/internal/impl/{DefaultDependencyFactory.java => DefaultDependencyCoordinateFactory.java} (64%) delete mode 100644 maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java index 58ab924af023..5ebbc9783d0e 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Artifact.java @@ -20,11 +20,8 @@ */ import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Immutable; - -import java.nio.file.Path; -import java.util.Optional; +import org.apache.maven.api.annotations.Nonnull; /** * An artifact points to a resource such as a jar file or war application. @@ -36,6 +33,20 @@ public interface Artifact { + /** + * Returns a unique identifier for this artifact. + * The identifier is composed of groupId, artifactId, version, classifier, extension + * @return the unique identifier + */ + default String key() + { + return getGroupId() + + ':' + getArtifactId() + + ':' + getExtension() + + ( getClassifier().length() > 0 ? ":" + getClassifier() : "" ) + + ':' + getVersion(); + } + /** * The groupId of the artifact. * @@ -52,14 +63,6 @@ public interface Artifact @Nonnull String getArtifactId(); - /** - * The classifier of the artifact. - * - * @return The classifier or an empty string if none, never {@code null}. - */ - @Nonnull - String getClassifier(); - /** * The version of the artifact. * @@ -69,20 +72,20 @@ public interface Artifact Version getVersion(); /** - * The file extension of the artifact. + * The classifier of the artifact. * - * @return The extension. + * @return The classifier or an empty string if none, never {@code null}. */ @Nonnull - String getExtension(); + String getClassifier(); /** - * The artifact type. + * The file extension of the artifact. * - * @return The artifact type, never {@code null}. + * @return The extension. */ @Nonnull - Type getType(); + String getExtension(); /** * Determines whether this artifact uses a snapshot version. @@ -93,12 +96,12 @@ public interface Artifact boolean isSnapshot(); /** - * Gets the file of this artifact. Note that only resolved artifacts have a file associated with them. In general, - * callers must not assume any relationship between an artifact's filename and its coordinates. + * Shortcut for {@code session.createArtifactCoordinate(artifact)} * - * @return The file or {@link Optional#empty()} if the artifact isn't resolved. + * @return an {@link ArtifactCoordinate} + * @see org.apache.maven.api.Session#createArtifactCoordinate(Artifact) */ @Nonnull - Optional getPath(); + ArtifactCoordinate toCoordinate(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Coordinate.java b/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinate.java similarity index 94% rename from api/maven-api-core/src/main/java/org/apache/maven/api/Coordinate.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinate.java index 2a92e2418891..1f11e321986f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Coordinate.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/ArtifactCoordinate.java @@ -31,7 +31,7 @@ */ @Experimental @Immutable -public interface Coordinate +public interface ArtifactCoordinate { /** @@ -74,14 +74,6 @@ public interface Coordinate @Nonnull String getExtension(); - /** - * The type of the artifact. - * - * @return The type. - */ - @Nonnull - Type getType(); - /** * Unique id identifying this artifact */ diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java index 2f9d19dbf7a9..51fa632efcc8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Dependency.java @@ -9,7 +9,7 @@ * "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 + * 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 @@ -19,28 +19,30 @@ * under the License. */ -import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.Nullable; -import org.apache.maven.api.annotations.Immutable; -import java.util.Collection; - -/** - * - * @since 4.0 - */ -@Experimental -@Immutable -public interface Dependency extends Coordinate +public interface Dependency extends Artifact { + + /** + * The artifact type. + * + * @return The artifact type, never {@code null}. + */ @Nonnull + Type getType(); + Scope getScope(); - @Nullable - Boolean getOptional(); + boolean isOptional(); + /** + * Shortcut for {@code session.createDependencyCoordinate(dependency)} + * + * @return an {@link DependencyCoordinate} + * @see org.apache.maven.api.Session#createDependencyCoordinate(Dependency) + */ @Nonnull - Collection getExclusions(); + DependencyCoordinate toCoordinate(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/DependencyCoordinate.java similarity index 60% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/DependencyCoordinate.java index ce5acaef5186..e5ea7a4cb6c2 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/DependencyCoordinate.java @@ -1,4 +1,4 @@ -package org.apache.maven.api.services; +package org.apache.maven.api; /* * Licensed to the Apache Software Foundation (ASF) under one @@ -9,7 +9,7 @@ * "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 + * 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 @@ -19,27 +19,36 @@ * under the License. */ -import java.util.List; - -import org.apache.maven.api.Node; import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.annotations.Immutable; + +import java.util.Collection; /** * * @since 4.0 */ @Experimental -public interface DependencyResolverResult +@Immutable +public interface DependencyCoordinate extends ArtifactCoordinate { /** - * Gets the exceptions that occurred while building the dependency graph. - * - * @return The list of exceptions {@link Exception}. + * The type of the artifact. + * + * @return The type. */ - List getCollectorExceptions(); + @Nonnull + Type getType(); + + @Nonnull + Scope getScope(); - Node getRoot(); + @Nullable + Boolean getOptional(); - List getArtifactResults(); + @Nonnull + Collection getExclusions(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java index 472edb8533ef..143c6d257ae4 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Exclusion.java @@ -26,7 +26,7 @@ * A dependency exlusion. * * @since 4.0 - * @see Dependency#getExclusions() + * @see DependencyCoordinate#getExclusions() */ @Experimental public interface Exclusion diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java index 6d8200071b09..f0bb78b17353 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Node.java @@ -38,10 +38,6 @@ @Immutable public interface Node { - /** - * @return artifact for this node - */ - Artifact getArtifact(); /** * @return dependency for this node diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java index 4dcdfde7a610..0531724b12d8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Project.java @@ -80,10 +80,10 @@ default Optional getBasedir() } @Nonnull - List getDependencies(); + List getDependencies(); @Nonnull - List getManagedDependencies(); + List getManagedDependencies(); @Nonnull default String getId() diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java index 98d22fc6e381..a68dc5256c02 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/ResolutionScope.java @@ -22,7 +22,11 @@ import java.util.Arrays; import java.util.Collections; import java.util.HashSet; +import java.util.Map; +import java.util.Optional; import java.util.Set; +import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.maven.api.annotations.Experimental; @@ -69,21 +73,18 @@ public enum ResolutionScope */ TEST( "test", Scope.COMPILE, Scope.SYSTEM, Scope.PROVIDED, Scope.RUNTIME, Scope.TEST ); - private final String id; - private final Set scopes; + private static final Map VALUES + = Stream.of( ResolutionScope.values() ).collect( Collectors.toMap( ResolutionScope::id, s -> s ) ); public static ResolutionScope fromString( String id ) { - for ( ResolutionScope scope : ResolutionScope.values() ) - { - if ( scope.id().equals( id ) ) - { - return scope; - } - } - throw new IllegalArgumentException( "Unknown resolution scope " + id ); + return Optional.ofNullable( VALUES.get( id ) ) + .orElseThrow( () -> new IllegalArgumentException( "Unknown resolution scope " + id ) ); } + private final String id; + private final Set scopes; + ResolutionScope( String id, Scope... scopes ) { this.id = id; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java index 2abb9ac71516..0d0cf07f9cb8 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/Session.java @@ -19,10 +19,6 @@ * under the License. */ -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.ThreadSafe; - import java.nio.file.Path; import java.time.Instant; import java.util.Collection; @@ -31,9 +27,12 @@ import java.util.NoSuchElementException; import java.util.Optional; import java.util.Properties; -import java.util.function.Predicate; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.ThreadSafe; import org.apache.maven.api.model.Repository; +import org.apache.maven.api.services.DependencyCoordinateFactory; import org.apache.maven.api.settings.Settings; /** @@ -174,14 +173,27 @@ public interface Session * Shortcut for getService(ArtifactFactory.class).create(...) * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String) */ - Coordinate createCoordinate( String groupId, String artifactId, String version, String extension ); + ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, String version, String extension ); + + /** + * Shortcut for getService(ArtifactFactory.class).create(...) + * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String, String, String) + */ + ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, String version, String classifier, + String extension, String type ); /** * Shortcut for getService(ArtifactFactory.class).create(...) * @see org.apache.maven.api.services.ArtifactFactory#create(Session, String, String, String, String, String, String) */ - Coordinate createCoordinate( String groupId, String artifactId, String version, String classifier, - String extension, String type ); + ArtifactCoordinate createArtifactCoordinate( Artifact artifact ); + + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate) + */ + @Nonnull + DependencyCoordinate createDependencyCoordinate( @Nonnull ArtifactCoordinate coordinate ); /** * Shortcut for getService(ArtifactFactory.class).create(...) @@ -198,20 +210,44 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri /** * Shortcut for getService(ArtifactResolver.class).resolve(...) - * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Coordinate) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Artifact resolveArtifact( ArtifactCoordinate coordinate ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Collection resolveArtifacts( ArtifactCoordinate... coordinates ); + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) * * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed */ - Artifact resolveArtifact( Coordinate coordinate ); + Collection resolveArtifacts( Collection coordinates ); /** * Shortcut for getService(ArtifactResolver.class).resolve(...) - * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Coordinate) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) * * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed */ Artifact resolveArtifact( Artifact artifact ); + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * @see org.apache.maven.api.services.ArtifactResolver#resolve(Session, Collection) + * + * @throws org.apache.maven.api.services.ArtifactResolverException if the artifact resolution failed + */ + Collection resolveArtifacts( Artifact... artifacts ); + /** * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} * @see org.apache.maven.api.services.ArtifactInstaller#install(Session, Collection) @@ -255,13 +291,6 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri */ boolean isVersionSnapshot( @Nonnull String version ); - /** - * Shortcut for getService(DependencyFactory.class).create(...) - * @see org.apache.maven.api.services.DependencyFactory#create(Session, Coordinate) - */ - @Nonnull - Dependency createDependency( @Nonnull Coordinate coordinate ); - /** * Shortcut for getService(DependencyCollector.class).collect(...) * @see org.apache.maven.api.services.DependencyCollector#collect(Session, Artifact) @@ -280,23 +309,14 @@ Artifact createArtifact( String groupId, String artifactId, String version, Stri @Nonnull Node collectDependencies( @Nonnull Project project ); - /** - * Shortcut for getService(DependencyCollector.class).collect(...) - * @see org.apache.maven.api.services.DependencyCollector#collect(Session, Dependency) - * - * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed - */ - @Nonnull - Node collectDependencies( @Nonnull Dependency dependency ); - /** * Shortcut for getService(DependencyResolver.class).resolve(...) - * @see org.apache.maven.api.services.DependencyResolver#resolve(Session, Dependency, Predicate) + * @see org.apache.maven.api.services.DependencyCollector#collect(Session, DependencyCoordinate) * - * @throws org.apache.maven.api.services.DependencyResolverException if the dependency resolution failed + * @throws org.apache.maven.api.services.DependencyCollectorException if the dependency collection failed */ @Nonnull - Node resolveDependencies( @Nonnull Dependency dependency ); + Node collectDependencies( @Nonnull DependencyCoordinate dependency ); Path getPathForLocalArtifact( @Nonnull Artifact artifact ); diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactory.java new file mode 100644 index 000000000000..a1da37134d91 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactory.java @@ -0,0 +1,71 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.Artifact; +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; + +/** + * Service used to create {@link ArtifactCoordinate} objects. + * + * @since 4.0 + */ +@Experimental +public interface ArtifactCoordinateFactory extends Service +{ + + /** + * Creates a coordinate. + * + * @param request the request holding coordinate creation parameters + * @return an {@code Artifact}, never {@code null} + * @throws IllegalArgumentException if {@code request} is null or {@code request.session} is null or invalid + */ + @Nonnull + ArtifactCoordinate create( @Nonnull ArtifactCoordinateFactoryRequest request ); + + @Nonnull + default ArtifactCoordinate create( @Nonnull Session session, String groupId, + String artifactId, String version, String extension ) + { + return create( ArtifactCoordinateFactoryRequest.build( session, groupId, artifactId, version, extension ) ); + } + + @Nonnull + default ArtifactCoordinate create( @Nonnull Session session, String groupId, String artifactId, String version, + String classifier, String extension, String type ) + { + return create( ArtifactCoordinateFactoryRequest.build( session, groupId, artifactId, + version, classifier, extension, type ) ); + } + + @Nonnull + default ArtifactCoordinate create( @Nonnull Session session, Artifact artifact ) + { + return create( ArtifactCoordinateFactoryRequest.build( session, + artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion().asString(), + artifact.getClassifier(), artifact.getExtension(), null ) ); + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactoryRequest.java similarity index 70% rename from api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactoryRequest.java rename to api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactoryRequest.java index ac474bff7fb6..8c8b9af06fb0 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactoryRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactCoordinateFactoryRequest.java @@ -19,6 +19,7 @@ * under the License. */ +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; @@ -26,13 +27,13 @@ import org.apache.maven.api.annotations.NotThreadSafe; /** - * A request for creating a {@link org.apache.maven.api.Coordinate} object. + * A request for creating a {@link ArtifactCoordinate} object. * * @since 4.0 */ @Experimental @Immutable -public interface CoordinateFactoryRequest +public interface ArtifactCoordinateFactoryRequest { @Nonnull @@ -50,10 +51,10 @@ public interface CoordinateFactoryRequest String getType(); - static CoordinateFactoryRequest build( Session session, String groupId, String artifactId, - String version, String extension ) + static ArtifactCoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String extension ) { - return CoordinateFactoryRequest.builder() + return ArtifactCoordinateFactoryRequest.builder() .session( session ) .groupId( groupId ) .artifactId( artifactId ) @@ -62,10 +63,10 @@ static CoordinateFactoryRequest build( Session session, String groupId, String a .build(); } - static CoordinateFactoryRequest build( Session session, String groupId, String artifactId, - String version, String classifier, String extension, String type ) + static ArtifactCoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String classifier, String extension, String type ) { - return CoordinateFactoryRequest.builder() + return ArtifactCoordinateFactoryRequest.builder() .session( session ) .groupId( groupId ) .artifactId( artifactId ) @@ -76,6 +77,19 @@ static CoordinateFactoryRequest build( Session session, String groupId, String a .build(); } + static ArtifactCoordinateFactoryRequest build( Session session, ArtifactCoordinate coordinate ) + { + return ArtifactCoordinateFactoryRequest.builder() + .session( session ) + .groupId( coordinate.getGroupId() ) + .artifactId( coordinate.getArtifactId() ) + .classifier( coordinate.getClassifier() ) + .version( coordinate.getVersion().asString() ) + .extension( coordinate.getExtension() ) + .build(); + } + + static ArtifactFactoryRequestBuilder builder() { return new ArtifactFactoryRequestBuilder(); @@ -134,13 +148,14 @@ public ArtifactFactoryRequestBuilder type( String type ) return this; } - public CoordinateFactoryRequest build() + public ArtifactCoordinateFactoryRequest build() { - return new DefaultArtifactFactoryRequest( session, groupId, artifactId, version, + return new DefaultArtifactFactoryRequestArtifact( session, groupId, artifactId, version, classifier, extension, type ); } - private static class DefaultArtifactFactoryRequest extends BaseRequest implements CoordinateFactoryRequest + private static class DefaultArtifactFactoryRequestArtifact extends BaseRequest implements + ArtifactCoordinateFactoryRequest { private final String groupId; private final String artifactId; @@ -149,13 +164,13 @@ private static class DefaultArtifactFactoryRequest extends BaseRequest implement private final String extension; private final String type; - DefaultArtifactFactoryRequest( @Nonnull Session session, - String groupId, - String artifactId, - String version, - String classifier, - String extension, - String type ) + DefaultArtifactFactoryRequestArtifact( @Nonnull Session session, + String groupId, + String artifactId, + String version, + String classifier, + String extension, + String type ) { super( session ); this.groupId = groupId; diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java index 516734365407..99f49d241d2b 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolver.java @@ -19,10 +19,11 @@ * under the License. */ -import org.apache.maven.api.Coordinate; +import java.util.Collection; + +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.Service; import org.apache.maven.api.Session; -import org.apache.maven.api.Artifact; import org.apache.maven.api.annotations.Experimental; /** @@ -45,16 +46,16 @@ public interface ArtifactResolver extends Service /** * @param session {@link Session} - * @param coordinate {@link Artifact} + * @param coordinates array of {@link ArtifactCoordinate} * @return {@link ArtifactResolverResult} * @throws ArtifactResolverException in case of an error. * @throws IllegalArgumentException in case of parameter {@code buildingRequest} is {@code null} or * parameter {@code coordinate} is {@code null} or invalid. */ default ArtifactResolverResult resolve( Session session, - Coordinate coordinate ) + Collection coordinates ) { - return resolve( ArtifactResolverRequest.build( session, coordinate ) ); + return resolve( ArtifactResolverRequest.build( session, coordinates ) ); } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java index 8c5d290168c8..f35f326f1453 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverRequest.java @@ -19,7 +19,9 @@ * under the License. */ -import org.apache.maven.api.Coordinate; +import java.util.Collection; + +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; @@ -39,7 +41,7 @@ public interface ArtifactResolverRequest Session getSession(); @Nonnull - Coordinate getCoordinate(); + Collection getCoordinates(); @Nonnull static ArtifactResolverRequestBuilder builder() @@ -48,11 +50,11 @@ static ArtifactResolverRequestBuilder builder() } @Nonnull - static ArtifactResolverRequest build( Session session, Coordinate coordinate ) + static ArtifactResolverRequest build( Session session, Collection coordinates ) { return builder() .session( session ) - .coordinate( coordinate ) + .coordinates( coordinates ) .build(); } @@ -60,7 +62,7 @@ static ArtifactResolverRequest build( Session session, Coordinate coordinate ) class ArtifactResolverRequestBuilder { Session session; - Coordinate coordinate; + Collection coordinates; @Nonnull public ArtifactResolverRequestBuilder session( Session session ) @@ -70,35 +72,35 @@ public ArtifactResolverRequestBuilder session( Session session ) } @Nonnull - public ArtifactResolverRequestBuilder coordinate( Coordinate artifact ) + public ArtifactResolverRequestBuilder coordinates( Collection coordinates ) { - this.coordinate = artifact; + this.coordinates = coordinates; return this; } @Nonnull public ArtifactResolverRequest build() { - return new DefaultArtifactResolverRequest( session, coordinate ); + return new DefaultArtifactResolverRequest( session, coordinates ); } private static class DefaultArtifactResolverRequest extends BaseRequest implements ArtifactResolverRequest { @Nonnull - private final Coordinate coordinate; + private final Collection coordinates; DefaultArtifactResolverRequest( @Nonnull Session session, - @Nonnull Coordinate coordinate ) + @Nonnull Collection coordinates ) { super( session ); - this.coordinate = nonNull( coordinate, "artifact can not be null" ); + this.coordinates = nonNull( coordinates, "coordinates can not be null" ); } @Nonnull @Override - public Coordinate getCoordinate() + public Collection getCoordinates() { - return coordinate; + return coordinates; } } } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java index 4d2eba4b0560..74bd5a74116f 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ArtifactResolverResult.java @@ -19,8 +19,12 @@ * under the License. */ +import java.nio.file.Path; +import java.util.Map; + import org.apache.maven.api.Artifact; import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; /** * The Artifact Result @@ -33,6 +37,7 @@ public interface ArtifactResolverResult /** * @return {@link Artifact} */ - Artifact getArtifact(); + @Nonnull + Map getArtifacts(); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java deleted file mode 100644 index d2cbaa1444e7..000000000000 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/CoordinateFactory.java +++ /dev/null @@ -1,94 +0,0 @@ -package org.apache.maven.api.services; - -/* - * 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. - */ - -import org.apache.maven.api.Artifact; -import org.apache.maven.api.Coordinate; -import org.apache.maven.api.Service; -import org.apache.maven.api.Session; -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.model.Dependency; -import org.apache.maven.api.model.Plugin; -import org.apache.maven.api.model.ReportPlugin; - -/** - * Service used to create {@link Coordinate} objects. - * - * @since 4.0 - */ -@Experimental -public interface CoordinateFactory extends Service -{ - - /** - * Creates a coordinate. - * - * @param request the request holding coordinate creation parameters - * @return an {@code Artifact}, never {@code null} - * @throws IllegalArgumentException if {@code request} is null or {@code request.session} is null or invalid - */ - @Nonnull - Coordinate create( @Nonnull CoordinateFactoryRequest request ); - - @Nonnull - default Coordinate create( @Nonnull Session session, String groupId, - String artifactId, String version, String extension ) - { - return create( CoordinateFactoryRequest.build( session, groupId, artifactId, version, extension ) ); - } - - @Nonnull - default Coordinate create( @Nonnull Session session, String groupId, String artifactId, String version, - String classifier, String extension, String type ) - { - return create( CoordinateFactoryRequest.build( session, groupId, artifactId, - version, classifier, extension, type ) ); - } - - @Nonnull - default Coordinate create( @Nonnull Session session, Dependency dependency ) - { - return create( CoordinateFactoryRequest.build( session, - dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), null ) ); - } - - @Nonnull - default Coordinate create( @Nonnull Session session, Artifact artifact ) - { - return create( CoordinateFactoryRequest.build( session, - artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion().asString(), - artifact.getClassifier(), artifact.getExtension(), artifact.getType().getName() ) ); - } - - @Nonnull - default Coordinate create( @Nonnull Session session, Plugin plugin ) - { - return create( CoordinateFactoryRequest.build( session, - plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(), null ) ); - } - - @Nonnull - default Coordinate create( @Nonnull Session session, ReportPlugin reportPlugin ) - { - return create( CoordinateFactoryRequest.build( session, - reportPlugin.getGroupId(), reportPlugin.getArtifactId(), reportPlugin.getVersion(), null ) ); - } -} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java index c06331f621b4..e21b2c46925d 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollector.java @@ -25,7 +25,7 @@ import org.apache.maven.api.Session; import org.apache.maven.api.Artifact; -import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; import org.apache.maven.api.Project; /** @@ -51,7 +51,7 @@ public interface DependencyCollector extends Service * @throws IllegalArgumentException if an argument is null or invalid * * @see DependencyCollector#collect(Session, Project) - * @see DependencyCollector#collect(Session, Dependency) + * @see DependencyCollector#collect(Session, DependencyCoordinate) * @see DependencyCollector#collect(Session, Artifact) */ @Nonnull @@ -71,7 +71,7 @@ public interface DependencyCollector extends Service */ @Nonnull default DependencyCollectorResult collect( @Nonnull Session session, - @Nonnull Dependency root ) + @Nonnull DependencyCoordinate root ) { return collect( DependencyCollectorRequest.build( session, root ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java index 7309e73b7f45..b0963205d6e5 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCollectorRequest.java @@ -26,7 +26,7 @@ import java.util.Optional; import org.apache.maven.api.Artifact; -import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; import org.apache.maven.api.Project; import org.apache.maven.api.Session; import org.apache.maven.api.annotations.Experimental; @@ -59,13 +59,13 @@ public interface DependencyCollectorRequest Optional getRootArtifact(); @Nonnull - Optional getRoot(); + Optional getRoot(); @Nonnull - Collection getDependencies(); + Collection getDependencies(); @Nonnull - Collection getManagedDependencies(); + Collection getManagedDependencies(); boolean getVerbose(); @@ -79,7 +79,7 @@ static DependencyCollectorRequest build( @Nonnull Session session, Artifact root } @Nonnull - static DependencyCollectorRequest build( @Nonnull Session session, @Nonnull Dependency root ) + static DependencyCollectorRequest build( @Nonnull Session session, @Nonnull DependencyCoordinate root ) { return builder() .session( nonNull( session, "session can not be null" ) ) @@ -112,9 +112,9 @@ class DependencyCollectorRequestBuilder Session session; Artifact rootArtifact; - Dependency root; - List dependencies = Collections.emptyList(); - List managedDependencies = Collections.emptyList(); + DependencyCoordinate root; + List dependencies = Collections.emptyList(); + List managedDependencies = Collections.emptyList(); boolean verbose; @Nonnull @@ -126,11 +126,11 @@ public DependencyCollectorRequestBuilder session( @Nonnull Session session ) /** * Sets the root artifact for the dependency graph. - * This must not be confused with {@link #root(Dependency)}: The root dependency, like any + * This must not be confused with {@link #root(DependencyCoordinate)}: The root dependency, like any * other specified dependency, will be subject to dependency collection/resolution, i.e. should have an artifact * descriptor and a corresponding artifact file. The root artifact on the other hand is only used * as a label for the root node of the graph in case no root dependency was specified. As such, the configured - * root artifact is ignored if {@link #root(Dependency)} has been set. + * root artifact is ignored if {@link #root(DependencyCoordinate)} has been set. * * @param rootArtifact The root artifact for the dependency graph, may be {@code null}. * @return This request for chaining, never {@code null}. @@ -147,7 +147,7 @@ public DependencyCollectorRequestBuilder rootArtifact( @Nullable Artifact rootAr * @return This request for chaining, never {@code null}. */ @Nonnull - public DependencyCollectorRequestBuilder root( @Nonnull Dependency root ) + public DependencyCollectorRequestBuilder root( @Nonnull DependencyCoordinate root ) { this.root = root; return this; @@ -162,7 +162,7 @@ public DependencyCollectorRequestBuilder root( @Nonnull Dependency root ) * @return This request for chaining, never {@code null}. */ @Nonnull - public DependencyCollectorRequestBuilder dependencies( @Nullable List dependencies ) + public DependencyCollectorRequestBuilder dependencies( @Nullable List dependencies ) { this.dependencies = ( dependencies != null ) ? dependencies : Collections.emptyList(); return this; @@ -175,7 +175,7 @@ public DependencyCollectorRequestBuilder dependencies( @Nullable List managedDependencies ) + public DependencyCollectorRequestBuilder managedDependencies( + @Nullable List managedDependencies ) { this.managedDependencies = ( managedDependencies != null ) ? managedDependencies : Collections.emptyList(); return this; @@ -212,7 +213,7 @@ public DependencyCollectorRequestBuilder managedDependencies( @Nullable List dependencies; - private final Collection managedDependencies; + private final DependencyCoordinate root; + private final Collection dependencies; + private final Collection managedDependencies; private final boolean verbose; @@ -270,9 +271,9 @@ static class DefaultDependencyCollectorRequest extends BaseRequest DefaultDependencyCollectorRequest( @Nonnull Session session, @Nullable Artifact rootArtifact, - @Nullable Dependency root, - @Nonnull Collection dependencies, - @Nonnull Collection managedDependencies, + @Nullable DependencyCoordinate root, + @Nonnull Collection dependencies, + @Nonnull Collection managedDependencies, boolean verbose ) { super( session ); @@ -292,21 +293,21 @@ public Optional getRootArtifact() @Nonnull @Override - public Optional getRoot() + public Optional getRoot() { return Optional.ofNullable( root ); } @Nonnull @Override - public Collection getDependencies() + public Collection getDependencies() { return dependencies; } @Nonnull @Override - public Collection getManagedDependencies() + public Collection getManagedDependencies() { return managedDependencies; } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactory.java new file mode 100644 index 000000000000..d3c7a6ffd7c3 --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactory.java @@ -0,0 +1,89 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Service; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.model.Dependency; +import org.apache.maven.api.model.Plugin; +import org.apache.maven.api.model.ReportPlugin; + +/** + * + * @since 4.0 + */ +@Experimental +public interface DependencyCoordinateFactory extends Service +{ + + /** + * Creates a new {@link DependencyCoordinate} object from the request. + * + * @param request the request containing the various data + * @return a new {@link DependencyCoordinate} object. + * + * @throws IllegalArgumentException if {@code request} is null or + * if {@code request.getSession()} is null or invalid + */ + @Nonnull + DependencyCoordinate create( @Nonnull DependencyCoordinateFactoryRequest request ); + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, @Nonnull ArtifactCoordinate coordinate ) + { + return create( DependencyCoordinateFactoryRequest.build( session, coordinate ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, @Nonnull org.apache.maven.api.Dependency dependency ) + { + return create( DependencyCoordinateFactoryRequest.build( session, dependency ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, Dependency dependency ) + { + return create( DependencyCoordinateFactoryRequest.build( session, + dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), + dependency.getClassifier(), null, dependency.getType() ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, Plugin plugin ) + { + // TODO: hard coded string + return create( DependencyCoordinateFactoryRequest.build( session, + plugin.getGroupId(), plugin.getArtifactId(), plugin.getVersion(), + null, null, "maven-plugin" ) ); + } + + @Nonnull + default DependencyCoordinate create( @Nonnull Session session, ReportPlugin reportPlugin ) + { + // TODO: hard coded string + return create( DependencyCoordinateFactoryRequest.build( session, + reportPlugin.getGroupId(), reportPlugin.getArtifactId(), reportPlugin.getVersion(), + null, null, "maven-plugin" ) ); + } +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactoryRequest.java new file mode 100644 index 000000000000..b42853cd5cdf --- /dev/null +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyCoordinateFactoryRequest.java @@ -0,0 +1,292 @@ +package org.apache.maven.api.services; + +/* + * 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. + */ + +import java.util.ArrayList; +import java.util.Collection; +import java.util.Collections; + +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Dependency; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Session; +import org.apache.maven.api.annotations.Experimental; +import org.apache.maven.api.annotations.Immutable; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.NotThreadSafe; + +/** + * + * @since 4.0 + */ +@Experimental +@Immutable +public interface DependencyCoordinateFactoryRequest extends ArtifactCoordinateFactoryRequest +{ + + String getScope(); + + boolean isOptional(); + + @Nonnull + Collection getExclusions(); + + static DependencyCoordinateFactoryRequest build( Session session, String groupId, String artifactId, + String version, String classifier, String extension, String type ) + { + return DependencyCoordinateFactoryRequest.builder() + .session( session ) + .groupId( groupId ) + .artifactId( artifactId ) + .version( version ) + .classifier( classifier ) + .extension( extension ) + .type( type ) + .build(); + } + + static DependencyCoordinateFactoryRequest build( Session session, ArtifactCoordinate coordinate ) + { + return builder() + .session( session ) + .groupId( coordinate.getGroupId() ) + .artifactId( coordinate.getArtifactId() ) + .version( coordinate.getVersion().asString() ) + .classifier( coordinate.getClassifier() ) + .extension( coordinate.getExtension() ) + .build(); + } + + static DependencyCoordinateFactoryRequest build( Session session, Dependency dependency ) + { + return builder() + .session( session ) + .groupId( dependency.getGroupId() ) + .artifactId( dependency.getArtifactId() ) + .version( dependency.getVersion().asString() ) + .classifier( dependency.getClassifier() ) + .extension( dependency.getExtension() ) + .type( dependency.getType().getName() ) + .scope( dependency.getScope().id() ) + .optional( dependency.isOptional() ) + .build(); + } + + static DependencyCoordinateFactoryRequestBuilder builder() + { + return new DependencyCoordinateFactoryRequestBuilder(); + } + + @NotThreadSafe + class DependencyCoordinateFactoryRequestBuilder + { + private Session session; + private String groupId; + private String artifactId; + private String version; + private String classifier; + private String extension; + private String type; + private String scope; + private boolean optional; + private Collection exclusions = Collections.emptyList(); + + public DependencyCoordinateFactoryRequestBuilder session( Session session ) + { + this.session = session; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder groupId( String groupId ) + { + this.groupId = groupId; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder artifactId( String artifactId ) + { + this.artifactId = artifactId; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder version( String version ) + { + this.version = version; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder classifier( String classifier ) + { + this.classifier = classifier; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder extension( String extension ) + { + this.extension = extension; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder type( String type ) + { + this.type = type; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder scope( String scope ) + { + this.scope = scope; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder optional( boolean optional ) + { + this.optional = optional; + return this; + } + + public DependencyCoordinateFactoryRequestBuilder exclusions( Collection exclusions ) + { + if ( exclusions != null ) + { + if ( this.exclusions.isEmpty() ) + { + this.exclusions = new ArrayList<>(); + } + this.exclusions.addAll( exclusions ); + } + return this; + } + + public DependencyCoordinateFactoryRequestBuilder exclusion( Exclusion exclusion ) + { + if ( exclusion != null ) + { + if ( this.exclusions.isEmpty() ) + { + this.exclusions = new ArrayList<>(); + } + this.exclusions.add( exclusion ); + } + return this; + } + + public DependencyCoordinateFactoryRequest build() + { + return new DefaultDependencyCoordinateFactoryRequest( session, groupId, artifactId, version, + classifier, extension, type, scope, optional, exclusions ); + } + + private static class DefaultDependencyCoordinateFactoryRequest + extends BaseRequest + implements DependencyCoordinateFactoryRequest + { + private final String groupId; + private final String artifactId; + private final String version; + private final String classifier; + private final String extension; + private final String type; + private final String scope; + private final boolean optional; + private final Collection exclusions; + + @SuppressWarnings( "checkstyle:ParameterNumber" ) + private DefaultDependencyCoordinateFactoryRequest( + @Nonnull Session session, String groupId, + String artifactId, + String version, + String classifier, + String extension, + String type, + String scope, + boolean optional, + Collection exclusions ) + { + super( session ); + this.groupId = groupId; + this.artifactId = artifactId; + this.version = version; + this.classifier = classifier; + this.extension = extension; + this.type = type; + this.scope = scope; + this.optional = optional; + this.exclusions = exclusions; + } + + @Override + public String getGroupId() + { + return groupId; + } + + @Override + public String getArtifactId() + { + return artifactId; + } + + @Override + public String getVersion() + { + return version; + } + + @Override + public String getClassifier() + { + return classifier; + } + + @Override + public String getExtension() + { + return extension; + } + + @Override + public String getType() + { + return type; + } + + @Override + public String getScope() + { + return scope; + } + + @Override + public boolean isOptional() + { + return optional; + } + + @Nonnull + @Override + public Collection getExclusions() + { + return exclusions; + } + } + } + +} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java deleted file mode 100644 index be4c39bc7c63..000000000000 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactory.java +++ /dev/null @@ -1,54 +0,0 @@ -package org.apache.maven.api.services; - -/* - * 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. - */ - -import org.apache.maven.api.Coordinate; -import org.apache.maven.api.Dependency; -import org.apache.maven.api.Service; -import org.apache.maven.api.Session; -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Nonnull; - -/** - * - * @since 4.0 - */ -@Experimental -public interface DependencyFactory extends Service -{ - - /** - * Creates a new {@link Dependency} object from the request. - * - * @param request the request containing the various data - * @return a new {@link Dependency} object. - * - * @throws IllegalArgumentException if {@code request} is null or - * if {@code request.getSession()} is null or invalid - */ - @Nonnull - Dependency create( @Nonnull DependencyFactoryRequest request ); - - @Nonnull - default Dependency create( @Nonnull Session session, @Nonnull Coordinate coordinate ) - { - return create( DependencyFactoryRequest.build( session, coordinate ) ); - } -} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java deleted file mode 100644 index 4dd5ac9ce18e..000000000000 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyFactoryRequest.java +++ /dev/null @@ -1,176 +0,0 @@ -package org.apache.maven.api.services; - -/* - * 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. - */ - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; - -import org.apache.maven.api.Coordinate; -import org.apache.maven.api.Exclusion; -import org.apache.maven.api.Session; -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Immutable; -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.NotThreadSafe; - -/** - * - * @since 4.0 - */ -@Experimental -@Immutable -public interface DependencyFactoryRequest -{ - - @Nonnull - Session getSession(); - - Coordinate getCoordinate(); - - String getScope(); - - boolean isOptional(); - - @Nonnull - Collection getExclusions(); - - static DependencyFactoryRequest build( Session session, Coordinate coordinate ) - { - return builder() - .session( session ) - .coordinate( coordinate ) - .build(); - } - - static DependencyFactoryRequestBuilder builder() - { - return new DependencyFactoryRequestBuilder(); - } - - @NotThreadSafe - class DependencyFactoryRequestBuilder - { - private Session session; - private Coordinate coordinate; - private String scope; - private boolean optional; - private Collection exclusions = Collections.emptyList(); - - public DependencyFactoryRequestBuilder session( Session session ) - { - this.session = session; - return this; - } - - public DependencyFactoryRequestBuilder coordinate( Coordinate coordinate ) - { - this.coordinate = coordinate; - return this; - } - - public DependencyFactoryRequestBuilder scope( String scope ) - { - this.scope = scope; - return this; - } - - public DependencyFactoryRequestBuilder optional( boolean optional ) - { - this.optional = optional; - return this; - } - - public DependencyFactoryRequestBuilder exclusions( Collection exclusions ) - { - if ( exclusions != null ) - { - if ( this.exclusions.isEmpty() ) - { - this.exclusions = new ArrayList<>(); - } - this.exclusions.addAll( exclusions ); - } - return this; - } - - public DependencyFactoryRequestBuilder exclusion( Exclusion exclusion ) - { - if ( exclusion != null ) - { - if ( this.exclusions.isEmpty() ) - { - this.exclusions = new ArrayList<>(); - } - this.exclusions.add( exclusion ); - } - return this; - } - - public DependencyFactoryRequest build() - { - return new DefaultDependencyFactoryRequest( session, coordinate, scope, optional, exclusions ); - } - - private static class DefaultDependencyFactoryRequest extends BaseRequest implements DependencyFactoryRequest - { - private final Coordinate coordinate; - private final String scope; - private final boolean optional; - private final Collection exclusions; - - private DefaultDependencyFactoryRequest( @Nonnull Session session, Coordinate coordinate, String scope, - boolean optional, Collection exclusions ) - { - super( session ); - this.coordinate = coordinate; - this.scope = scope; - this.optional = optional; - this.exclusions = exclusions; - } - - @Override - public Coordinate getCoordinate() - { - return coordinate; - } - - @Override - public String getScope() - { - return scope; - } - - @Override - public boolean isOptional() - { - return optional; - } - - @Nonnull - @Override - public Collection getExclusions() - { - return exclusions; - } - } - } - -} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java deleted file mode 100644 index d97856710177..000000000000 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolver.java +++ /dev/null @@ -1,139 +0,0 @@ -package org.apache.maven.api.services; - -/* - * 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. - */ - -import java.util.function.Predicate; - -import org.apache.maven.api.Coordinate; -import org.apache.maven.api.Service; -import org.apache.maven.api.Session; -import org.apache.maven.api.Dependency; -import org.apache.maven.api.Node; -import org.apache.maven.api.Project; -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.Nullable; - -/** - * The DependencyResolver service can be used to collect the dependencies - * and download the artifacts. - * - * @since 4.0 - */ -@Experimental -public interface DependencyResolver extends Service -{ - /** - * Collect dependencies and resolve the artifacts. - * - * @param request {@link DependencyResolverRequest} - * @return the resolved dependencies. - * @throws DependencyResolverException in case of an error. - * @throws IllegalArgumentException if {@code request} is null or invalid - */ - DependencyResolverResult resolve( DependencyResolverRequest request ); - - /** - * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. - * - * @param session The {@link Session}, must not be {@code null}. - * @param coordinate {@link Coordinate} - * @return the resolved dependencies. - * @throws DependencyResolverException in case of an error. - * @throws IllegalArgumentException if {@code request} is null or invalid - */ - @Nonnull - default DependencyResolverResult resolve( @Nonnull Session session, - @Nonnull Coordinate coordinate ) - { - return resolve( session, session.createDependency( coordinate ) ); - } - - /** - * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. - * - * @param session The {@link Session}, must not be {@code null}. - * @param coordinate {@link Coordinate} - * @return the resolved dependencies. - * @throws DependencyResolverException in case of an error. - * @throws IllegalArgumentException if {@code request} is null or invalid - */ - @Nonnull - default DependencyResolverResult resolve( @Nonnull Session session, - @Nonnull Coordinate coordinate, - @Nullable Predicate filter ) - { - return resolve( session, session.createDependency( coordinate ), filter ); - } - - /** - * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. - * - * @param session The {@link Session}, must not be {@code null}. - * @param root {@link Dependency} - * @return the resolved dependencies. - * @throws DependencyResolverException in case of an error. - * @throws IllegalArgumentException if {@code request} is null or invalid - */ - @Nonnull - default DependencyResolverResult resolve( @Nonnull Session session, - @Nonnull Dependency root ) - { - return resolve( session, root, null ); - } - - /** - * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. - * - * @param session The {@link Session}, must not be {@code null}. - * @param root {@link Dependency} - * @param filter {@link Predicate} used to eventually filter out some dependencies - * when downloading (can be {@code null}). - * @return the resolved dependencies. - * @throws DependencyResolverException in case of an error. - * @throws IllegalArgumentException if {@code request} is null or invalid - */ - @Nonnull - default DependencyResolverResult resolve( @Nonnull Session session, - @Nonnull Dependency root, - @Nullable Predicate filter ) - { - return resolve( DependencyResolverRequest.build( session, root, filter ) ); - } - - /** - * This will resolve the dependencies of the coordinate, not resolving the artifact of the coordinate itself. - * - * @param session The {@link Session}, must not be {@code null}. - * @param project {@link Project} - * @param filter {@link Predicate} (can be {@code null}). - * @return the resolved dependencies. - * @throws DependencyResolverException in case of an error. - * @throws IllegalArgumentException if {@code session} or {@code project} is null or invalid - */ - @Nonnull - default DependencyResolverResult resolve( @Nonnull Session session, - @Nonnull Project project, - @Nullable Predicate filter ) - { - return resolve( DependencyResolverRequest.build( session, project, filter ) ); - } - -} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java deleted file mode 100644 index 9aca3afd560a..000000000000 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverException.java +++ /dev/null @@ -1,59 +0,0 @@ -package org.apache.maven.api.services; - -/* - * 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. - */ - -import org.apache.maven.api.annotations.Experimental; - -/** - * The Exception class in case a resolving does not work. - * - * @since 4.0 - */ -@Experimental -public class DependencyResolverException - extends MavenException -{ - private static final long serialVersionUID = 5320065249974323888L; - - /** - * @param cause The {@link Exception cause} of the problem. - */ - protected DependencyResolverException( Exception cause ) - { - super( cause ); - } - - /** - * @param message The message to give. - * @param e The {@link Exception}. - */ - public DependencyResolverException( String message, Exception e ) - { - super( message, e ); - } - - /** - * @return {@link DependencyResolverResult} - */ - public DependencyResolverResult getResult() - { - return null; - } -} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java deleted file mode 100644 index 79bce874c0f3..000000000000 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/DependencyResolverRequest.java +++ /dev/null @@ -1,354 +0,0 @@ -package org.apache.maven.api.services; - -/* - * 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. - */ - -import org.apache.maven.api.annotations.Experimental; -import org.apache.maven.api.annotations.Immutable; -import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.annotations.NotThreadSafe; -import org.apache.maven.api.annotations.Nullable; - -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Optional; -import java.util.function.Predicate; - -import org.apache.maven.api.Session; -import org.apache.maven.api.Artifact; -import org.apache.maven.api.Dependency; -import org.apache.maven.api.Node; -import org.apache.maven.api.Project; - -import static org.apache.maven.api.services.BaseRequest.nonNull; - -/** - * A request to collect and resolve a dependency graph. - * - * @since 4.0 - */ -@Experimental -@Immutable -public interface DependencyResolverRequest extends DependencyCollectorRequest -{ - - @Nonnull - Optional> getFilter(); - - @Nonnull - static DependencyResolverRequest build( @Nonnull Session session, - @Nonnull Artifact root ) - { - return build( session, root , null ); - } - - @Nonnull - static DependencyResolverRequest build( @Nonnull Session session, - @Nonnull Artifact root, - @Nullable Predicate filter ) - { - return builder() - .session( nonNull( session, "session can not be null" ) ) - .rootArtifact( nonNull( root, "root can not be null" ) ) - .filter( filter ) - .build(); - } - - @Nonnull - static DependencyResolverRequest build( @Nonnull Session session, - @Nonnull Dependency root ) - { - return build( session, root, null ); - } - - @Nonnull - static DependencyResolverRequest build( @Nonnull Session session, - @Nonnull Dependency root, - @Nullable Predicate filter ) - { - return builder() - .session( nonNull( session, "session can not be null" ) ) - .root( nonNull( root, "root can not be null" ) ) - .filter( filter ) - .build(); - } - - @Nonnull - static DependencyResolverRequest build( @Nonnull Session session, - @Nonnull Project project ) - { - return build( session, project, null ); - } - - @Nonnull - static DependencyResolverRequest build( @Nonnull Session session, - @Nonnull Project project, - @Nullable Predicate filter ) - { - nonNull( session, "session can not be null" ); - nonNull( project, "project can not be null" ); - return builder() - .session( session ) - .rootArtifact( project.getArtifact() ) - .dependencies( project.getDependencies() ) - .managedDependencies( project.getManagedDependencies() ) - .filter( filter ) - .build(); - } - - @Nonnull - static DependencyResolverRequestBuilder builder() - { - return new DependencyResolverRequestBuilder(); - } - - @NotThreadSafe - class DependencyResolverRequestBuilder - { - Session session; - Artifact rootArtifact; - Dependency root; - List dependencies = Collections.emptyList(); - List managedDependencies = Collections.emptyList(); - Predicate filter; - boolean verbose; - - @Nonnull - public DependencyResolverRequestBuilder session( @Nonnull Session session ) - { - this.session = session; - return this; - } - - /** - * Sets the root artifact for the dependency graph. - * This must not be confused with {@link #root(Dependency)}: The root dependency, like - * any other specified dependency, will be subject to dependency collection/resolution, i.e. should have an - * artifact descriptor and a corresponding artifact file. The root artifact on the other hand is only - * used as a label for the root node of the graph in case no root dependency was specified. As such, the - * configured root artifact is ignored if {@link #root(Dependency)} has not been called. - * - * @param rootArtifact The root artifact for the dependency graph, may be {@code null}. - * @return This request for chaining, never {@code null}. - */ - @Nonnull - public DependencyResolverRequestBuilder rootArtifact( Artifact rootArtifact ) - { - this.rootArtifact = rootArtifact; - return this; - } - - /** - * - * @param root The root dependency - * @return This request for chaining, never {@code null}. - */ - @Nonnull - public DependencyResolverRequestBuilder root( @Nonnull Dependency root ) - { - this.root = root; - return this; - } - - /** - * Sets the direct dependencies. If both a root dependency and direct dependencies are given in the request, the - * direct dependencies from the request will be merged with the direct dependencies from the root dependency's - * artifact descriptor, giving higher priority to the dependencies from the request. - * - * @param dependencies The direct dependencies, may be {@code null}. - * @return This request for chaining, never {@code null}. - */ - @Nonnull - public DependencyResolverRequestBuilder dependencies( List dependencies ) - { - this.dependencies = ( dependencies != null ) ? dependencies : Collections.emptyList(); - return this; - } - - /** - * Adds the specified direct dependency. - * - * @param dependency The dependency to add, may be {@code null}. - * @return This request for chaining, never {@code null}. - */ - @Nonnull - public DependencyResolverRequestBuilder dependency( @Nullable Dependency dependency ) - { - if ( dependency != null ) - { - if ( this.dependencies.isEmpty() ) - { - this.dependencies = new ArrayList<>(); - } - this.dependencies.add( dependency ); - } - return this; - } - - - /** - * Sets the dependency management to apply to transitive dependencies. To clarify, this management does not - * apply to - * the direct dependencies of the root node. - * - * @param managedDependencies The dependency management, may be {@code null}. - * @return This request for chaining, never {@code null}. - */ - @Nonnull - public DependencyResolverRequestBuilder managedDependencies( List managedDependencies ) - { - this.managedDependencies = ( managedDependencies != null ) ? managedDependencies : Collections.emptyList(); - return this; - } - - /** - * Adds the specified managed dependency. - * - * @param managedDependency The managed dependency to add, may be {@code null}. - * @return This request for chaining, never {@code null}. - */ - @Nonnull - public DependencyResolverRequestBuilder managedDependency( @Nullable Dependency managedDependency ) - { - if ( managedDependency != null ) - { - if ( this.managedDependencies.isEmpty() ) - { - this.managedDependencies = new ArrayList<>(); - } - this.managedDependencies.add( managedDependency ); - } - return this; - } - - @Nonnull - public DependencyResolverRequestBuilder filter( @Nullable Predicate filter ) - { - this.filter = filter; - return this; - } - - @Nonnull - public DependencyResolverRequestBuilder verbose( boolean verbose ) - { - this.verbose = verbose; - return this; - } - - @Nonnull - public DependencyResolverRequest build() - { - return new DefaultDependencyResolverRequest( - session, - rootArtifact, - root, - dependencies, - managedDependencies, - filter, - verbose ); - } - - private static class DefaultDependencyResolverRequest extends BaseRequest - implements DependencyResolverRequest - { - private final Artifact rootArtifact; - private final Dependency root; - private final Collection dependencies; - private final Collection managedDependencies; - private final Predicate filter; - private final boolean verbose; - - - /** - * Creates a request with the specified properties. - * - * @param session {@link Session} - * @param rootArtifact The root dependency whose transitive dependencies should be collected, may be {@code - * null}. - */ - DefaultDependencyResolverRequest( - @Nonnull Session session, - @Nullable Artifact rootArtifact, - @Nullable Dependency root, - @Nullable Collection dependencies, - @Nullable Collection managedDependencies, - @Nullable Predicate filter, - boolean verbose ) - { - super( session ); - this.rootArtifact = rootArtifact; - this.root = root; - this.dependencies = unmodifiable( dependencies ); - this.managedDependencies = unmodifiable( managedDependencies ); - this.filter = filter; - this.verbose = verbose; - } - - @Nonnull - @Override - public Optional getRootArtifact() - { - return Optional.ofNullable( rootArtifact ); - } - - @Nonnull - @Override - public Optional getRoot() - { - return Optional.ofNullable( root ); - } - - @Nonnull - @Override - public Collection getDependencies() - { - return dependencies; - } - - @Nonnull - @Override - public Collection getManagedDependencies() - { - return managedDependencies; - } - - @Nonnull - @Override - public Optional> getFilter() - { - return Optional.ofNullable( filter ); - } - - @Override - public boolean getVerbose() - { - return verbose; - } - - @Override - public String toString() - { - return getRoot() + " -> " + getDependencies(); - } - - } - } -} diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java index 986d8084b855..d7829752f958 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilder.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.Coordinate; +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.Service; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Nonnull; @@ -96,13 +96,13 @@ default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Artifact * Creates a {@link org.apache.maven.api.Project} from a coordinate. * * @param session The {@link Session}, must not be {@code null}. - * @param coordinate The {@link Coordinate}, must not be {@code null}. + * @param coordinate The {@link ArtifactCoordinate}, must not be {@code null}. * @throws ProjectBuilderException if the project can not be created * @throws IllegalArgumentException if an argument is {@code null} or invalid * @see #build(ProjectBuilderRequest) */ @Nonnull - default ProjectBuilderResult build( @Nonnull Session session, @Nonnull Coordinate coordinate ) + default ProjectBuilderResult build( @Nonnull Session session, @Nonnull ArtifactCoordinate coordinate ) { return build( ProjectBuilderRequest.build( session, coordinate ) ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java index 10dd3c36eff7..4b90e8bfd559 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderRequest.java @@ -19,7 +19,7 @@ * under the License. */ -import org.apache.maven.api.Coordinate; +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.annotations.Experimental; import org.apache.maven.api.annotations.Immutable; import org.apache.maven.api.annotations.Nonnull; @@ -58,7 +58,7 @@ public interface ProjectBuilderRequest Optional getArtifact(); @Nonnull - Optional getCoordinate(); + Optional getCoordinate(); boolean isAllowStubModel(); @@ -96,7 +96,7 @@ static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Artifact } @Nonnull - static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull Coordinate coordinate ) + static ProjectBuilderRequest build( @Nonnull Session session, @Nonnull ArtifactCoordinate coordinate ) { return builder() .session( nonNull( session, "session can not be null" ) ) @@ -117,7 +117,7 @@ class ProjectBuilderRequestBuilder Path path; ProjectBuilderSource source; Artifact artifact; - Coordinate coordinate; + ArtifactCoordinate coordinate; boolean allowStubModel; boolean recursive; boolean processPlugins = true; @@ -147,7 +147,7 @@ public ProjectBuilderRequestBuilder artifact( Artifact artifact ) return this; } - public ProjectBuilderRequestBuilder coordinate( Coordinate coordinate ) + public ProjectBuilderRequestBuilder coordinate( ArtifactCoordinate coordinate ) { this.coordinate = coordinate; return this; @@ -177,7 +177,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest private final Path path; private final ProjectBuilderSource source; private final Artifact artifact; - private final Coordinate coordinate; + private final ArtifactCoordinate coordinate; private final boolean allowStubModel; private final boolean recursive; private final boolean processPlugins; @@ -188,7 +188,7 @@ private static class DefaultProjectBuilderRequest extends BaseRequest @Nullable Path path, @Nullable ProjectBuilderSource source, @Nullable Artifact artifact, - @Nullable Coordinate coordinate, + @Nullable ArtifactCoordinate coordinate, boolean allowStubModel, boolean recursive, boolean processPlugins, @@ -228,7 +228,7 @@ public Optional getArtifact() @Nonnull @Override - public Optional getCoordinate() + public Optional getCoordinate() { return Optional.ofNullable( coordinate ); } diff --git a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java index ba3c60fb6fc4..a76b6cab2ffb 100644 --- a/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java +++ b/api/maven-api-core/src/main/java/org/apache/maven/api/services/ProjectBuilderResult.java @@ -78,6 +78,6 @@ public interface ProjectBuilderResult * @return The result of the dependency resolution for the project. */ @Nonnull - Optional getDependencyResolverResult(); + Optional getDependencyResolverResult(); } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java index 85f262cc85e0..de1bfdc6299d 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/AbstractSession.java @@ -30,12 +30,13 @@ import java.util.Optional; import java.util.WeakHashMap; import java.util.concurrent.CopyOnWriteArrayList; -import java.util.function.Predicate; import java.util.stream.Collectors; +import java.util.stream.Stream; import org.apache.maven.api.Artifact; -import org.apache.maven.api.Coordinate; +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; import org.apache.maven.api.Listener; import org.apache.maven.api.LocalRepository; import org.apache.maven.api.Metadata; @@ -47,6 +48,7 @@ import org.apache.maven.api.VersionRange; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.model.Repository; +import org.apache.maven.api.services.ArtifactCoordinateFactory; import org.apache.maven.api.services.ArtifactDeployer; import org.apache.maven.api.services.ArtifactDeployerException; import org.apache.maven.api.services.ArtifactFactory; @@ -55,12 +57,9 @@ import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactResolver; import org.apache.maven.api.services.ArtifactResolverException; -import org.apache.maven.api.services.CoordinateFactory; import org.apache.maven.api.services.DependencyCollector; import org.apache.maven.api.services.DependencyCollectorException; -import org.apache.maven.api.services.DependencyFactory; -import org.apache.maven.api.services.DependencyResolver; -import org.apache.maven.api.services.DependencyResolverException; +import org.apache.maven.api.services.DependencyCoordinateFactory; import org.apache.maven.api.services.LocalRepositoryManager; import org.apache.maven.api.services.RepositoryFactory; import org.apache.maven.api.services.VersionParser; @@ -165,14 +164,14 @@ public List toArtifactRepositories( List r public abstract ArtifactRepository toArtifactRepository( RemoteRepository repository ); - public List toDependencies( Collection dependencies ) + public List toDependencies( Collection dependencies ) { return dependencies == null ? null : dependencies.stream() .map( this::toDependency ) .collect( Collectors.toList() ); } - public abstract org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ); + public abstract org.eclipse.aether.graph.Dependency toDependency( DependencyCoordinate dependency ); public List toArtifacts( Collection artifacts ) { @@ -203,11 +202,11 @@ public org.eclipse.aether.artifact.Artifact toArtifact( Artifact artifact ) ); } - public org.eclipse.aether.artifact.Artifact toArtifact( Coordinate coord ) + public org.eclipse.aether.artifact.Artifact toArtifact( ArtifactCoordinate coord ) { - if ( coord instanceof DefaultCoordinate ) + if ( coord instanceof DefaultArtifactCoordinate ) { - return ( ( DefaultCoordinate ) coord ).getCoordinate(); + return ( (DefaultArtifactCoordinate) coord ).getCoordinate(); } return new org.eclipse.aether.artifact.DefaultArtifact( coord.getGroupId(), @@ -313,25 +312,39 @@ public RemoteRepository createRemoteRepository( @Nonnull Repository repository ) * @see ArtifactFactory#create(Session, String, String, String, String) */ @Override - public Coordinate createCoordinate( String groupId, String artifactId, String version, String extension ) + public ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, + String version, String extension ) { - return getService( CoordinateFactory.class ) + return getService( ArtifactCoordinateFactory.class ) .create( this, groupId, artifactId, version, extension ); } /** * Shortcut for getService(CoordinateFactory.class).create(...) * - * @see CoordinateFactory#create(Session, String, String, String, String, String, String) + * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String) */ @Override - public Coordinate createCoordinate( String groupId, String artifactId, String version, String classifier, - String extension, String type ) + public ArtifactCoordinate createArtifactCoordinate( String groupId, String artifactId, String version, + String classifier, String extension, String type ) { - return getService( CoordinateFactory.class ) + return getService( ArtifactCoordinateFactory.class ) .create( this, groupId, artifactId, version, classifier, extension, type ); } + /** + * Shortcut for getService(CoordinateFactory.class).create(...) + * + * @see ArtifactCoordinateFactory#create(Session, String, String, String, String, String, String) + */ + @Override + public ArtifactCoordinate createArtifactCoordinate( Artifact artifact ) + { + return getService( ArtifactCoordinateFactory.class ) + .create( this, artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion().asString(), + artifact.getClassifier(), artifact.getExtension(), null ); + } + /** * Shortcut for getService(ArtifactFactory.class).create(...) * @@ -361,30 +374,66 @@ public Artifact createArtifact( String groupId, String artifactId, String versio * Shortcut for getService(ArtifactResolver.class).resolve(...) * * @throws ArtifactResolverException if the artifact resolution failed - * @see ArtifactResolver#resolve(Session, Coordinate) + * @see ArtifactResolver#resolve(Session, Collection) + */ + @Override + public Artifact resolveArtifact( ArtifactCoordinate coordinate ) + { + return getService( ArtifactResolver.class ) + .resolve( this, Collections.singletonList( coordinate ) ) + .getArtifacts().keySet().iterator().next(); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Collection) + */ + @Override + public Collection resolveArtifacts( ArtifactCoordinate... coordinates ) + { + return resolveArtifacts( Arrays.asList( coordinates ) ); + } + + /** + * Shortcut for getService(ArtifactResolver.class).resolve(...) + * + * @throws ArtifactResolverException if the artifact resolution failed + * @see ArtifactResolver#resolve(Session, Collection) */ @Override - public Artifact resolveArtifact( Coordinate coordinate ) + public Collection resolveArtifacts( Collection coordinates ) { return getService( ArtifactResolver.class ) - .resolve( this, coordinate ) - .getArtifact(); + .resolve( this, coordinates ) + .getArtifacts().keySet(); } /** * Shortcut for getService(ArtifactResolver.class).resolve(...) * * @throws ArtifactResolverException if the artifact resolution failed - * @see ArtifactResolver#resolve(Session, Coordinate) + * @see ArtifactResolver#resolve(Session, Collection) */ @Override public Artifact resolveArtifact( Artifact artifact ) { - Coordinate coordinate = getService( CoordinateFactory.class ) + ArtifactCoordinate coordinate = getService( ArtifactCoordinateFactory.class ) .create( this, artifact ); return resolveArtifact( coordinate ); } + @Override + public Collection resolveArtifacts( Artifact... artifacts ) + { + ArtifactCoordinateFactory acf = getService( ArtifactCoordinateFactory.class ); + ArtifactCoordinate[] coords = Stream.of( artifacts ) + .map( a -> acf.create( this, a ) ) + .toArray( ArtifactCoordinate[]::new ); + return resolveArtifacts( coords ); + } + /** * Shortcut for {@code getService(ArtifactInstaller.class).install(...)} * @@ -463,16 +512,28 @@ public boolean isVersionSnapshot( @Nonnull String version ) /** * Shortcut for getService(DependencyFactory.class).create(...) * - * @see DependencyFactory#create(Session, Coordinate) + * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate) */ @Nonnull @Override - public Dependency createDependency( @Nonnull Coordinate coordinate ) + public DependencyCoordinate createDependencyCoordinate( @Nonnull ArtifactCoordinate coordinate ) { - return getService( DependencyFactory.class ) + return getService( DependencyCoordinateFactory.class ) .create( this, coordinate ); } + /** + * Shortcut for getService(DependencyFactory.class).create(...) + * + * @see DependencyCoordinateFactory#create(Session, ArtifactCoordinate) + */ + @Nonnull + public DependencyCoordinate createDependencyCoordinate( @Nonnull Dependency dependency ) + { + return getService( DependencyCoordinateFactory.class ) + .create( this, dependency ); + } + /** * Shortcut for getService(DependencyCollector.class).collect(...) * @@ -507,32 +568,17 @@ public Node collectDependencies( @Nonnull Project project ) * Shortcut for getService(DependencyCollector.class).collect(...) * * @throws DependencyCollectorException if the dependency collection failed - * @see DependencyCollector#collect(Session, Dependency) + * @see DependencyCollector#collect(Session, DependencyCoordinate) */ @Nonnull @Override - public Node collectDependencies( @Nonnull Dependency dependency ) + public Node collectDependencies( @Nonnull DependencyCoordinate dependency ) { return getService( DependencyCollector.class ) .collect( this, dependency ) .getRoot(); } - /** - * Shortcut for getService(DependencyResolver.class).resolve(...) - * - * @throws DependencyResolverException if the dependency resolution failed - * @see DependencyResolver#resolve(Session, Dependency, Predicate) - */ - @Nonnull - @Override - public Node resolveDependencies( @Nonnull Dependency dependency ) - { - return getService( DependencyResolver.class ) - .resolve( this, dependency, null ) - .getRoot(); - } - @Override public Path getPathForLocalArtifact( @Nonnull Artifact artifact ) { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java index 53cc338d3a4d..54b5ff372501 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifact.java @@ -19,18 +19,12 @@ * under the License. */ -import org.apache.maven.api.Type; -import org.apache.maven.api.Version; -import org.apache.maven.api.annotations.Nonnull; - -import java.io.File; -import java.nio.file.Path; import java.util.Objects; -import java.util.Optional; import org.apache.maven.api.Artifact; -import org.apache.maven.api.services.TypeRegistry; -import org.eclipse.aether.artifact.ArtifactProperties; +import org.apache.maven.api.ArtifactCoordinate; +import org.apache.maven.api.Version; +import org.apache.maven.api.annotations.Nonnull; import static org.apache.maven.internal.impl.Utils.nonNull; @@ -41,11 +35,17 @@ public class DefaultArtifact implements Artifact { private final @Nonnull AbstractSession session; private final @Nonnull org.eclipse.aether.artifact.Artifact artifact; + private final String id; public DefaultArtifact( @Nonnull AbstractSession session, @Nonnull org.eclipse.aether.artifact.Artifact artifact ) { this.session = nonNull( session, "session can not be null" ); this.artifact = nonNull( artifact, "artifact can not be null" ); + this.id = getGroupId() + + ':' + getArtifactId() + + ':' + getExtension() + + ( getClassifier().length() > 0 ? ":" + getClassifier() : "" ) + + ':' + getVersion(); } public org.eclipse.aether.artifact.Artifact getArtifact() @@ -53,6 +53,12 @@ public org.eclipse.aether.artifact.Artifact getArtifact() return artifact; } + @Override + public String key() + { + return id; + } + @Nonnull @Override public String getGroupId() @@ -81,13 +87,6 @@ public String getExtension() return artifact.getExtension(); } - @Override - public Type getType() - { - String type = artifact.getProperty( ArtifactProperties.TYPE, artifact.getExtension() ); - return session.getService( TypeRegistry.class ).getType( type ); - } - @Nonnull @Override public String getClassifier() @@ -98,40 +97,27 @@ public String getClassifier() @Override public boolean isSnapshot() { - return DefaultVersionParser.checkSnapshot( artifact.toString() ); + return DefaultVersionParser.checkSnapshot( artifact.getVersion() ); } - @Nonnull @Override - public Optional getPath() + public ArtifactCoordinate toCoordinate() { - return Optional.ofNullable( artifact.getFile() ).map( File::toPath ); + return session.createArtifactCoordinate( this ); } @Override public boolean equals( Object o ) { - if ( this == o ) - { - return true; - } - if ( o == null || getClass() != o.getClass() ) - { - return false; - } - DefaultArtifact that = (DefaultArtifact) o; - return Objects.equals( this.getGroupId(), that.getGroupId() ) - && Objects.equals( this.getArtifactId(), that.getArtifactId() ) - && Objects.equals( this.getVersion(), that.getVersion() ) - && Objects.equals( this.getClassifier(), that.getClassifier() ) - && Objects.equals( this.getExtension(), that.getExtension() ); + return o instanceof DefaultArtifact + && Objects.equals( id, ( (DefaultArtifact) o ).id ); } @Override public int hashCode() { - return Objects.hash( getGroupId(), getArtifactId(), getVersion(), getClassifier(), getExtension() ); + return id.hashCode(); } @Override diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinate.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinate.java similarity index 78% rename from maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinate.java rename to maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinate.java index 90830609f703..3386ff56e588 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinate.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinate.java @@ -21,25 +21,22 @@ import java.util.Objects; -import org.apache.maven.api.Coordinate; -import org.apache.maven.api.Type; +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.VersionRange; import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.services.TypeRegistry; -import org.eclipse.aether.artifact.ArtifactProperties; import static org.apache.maven.internal.impl.Utils.nonNull; /** * A wrapper class around a maven resolver artifact. */ -public class DefaultCoordinate implements Coordinate +public class DefaultArtifactCoordinate implements ArtifactCoordinate { private final @Nonnull AbstractSession session; private final @Nonnull org.eclipse.aether.artifact.Artifact coordinate; - public DefaultCoordinate( @Nonnull AbstractSession session, - @Nonnull org.eclipse.aether.artifact.Artifact coordinate ) + public DefaultArtifactCoordinate( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.artifact.Artifact coordinate ) { this.session = nonNull( session, "session can not be null" ); this.coordinate = nonNull( coordinate, "coordinate can not be null" ); @@ -77,13 +74,6 @@ public String getExtension() return coordinate.getExtension(); } - @Override - public Type getType() - { - String type = coordinate.getProperty( ArtifactProperties.TYPE, coordinate.getExtension() ); - return session.getService( TypeRegistry.class ).getType( type ); - } - @Nonnull @Override public String getClassifier() @@ -102,18 +92,17 @@ public boolean equals( Object o ) { return false; } - DefaultCoordinate that = (DefaultCoordinate) o; + DefaultArtifactCoordinate that = (DefaultArtifactCoordinate) o; return Objects.equals( this.getGroupId(), that.getGroupId() ) && Objects.equals( this.getArtifactId(), that.getArtifactId() ) && Objects.equals( this.getVersion(), that.getVersion() ) - && Objects.equals( this.getClassifier(), that.getClassifier() ) - && Objects.equals( this.getType(), that.getType() ); + && Objects.equals( this.getClassifier(), that.getClassifier() ); } @Override public int hashCode() { - return Objects.hash( getGroupId(), getArtifactId(), getVersion(), getClassifier(), getType() ); + return Objects.hash( getGroupId(), getArtifactId(), getVersion(), getClassifier() ); } @Override diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinateFactory.java similarity index 84% rename from maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java rename to maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinateFactory.java index eca9012b9582..b6edcd57264a 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultCoordinateFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactCoordinateFactory.java @@ -21,10 +21,10 @@ import javax.inject.Named; -import org.apache.maven.api.Coordinate; +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.services.CoordinateFactory; -import org.apache.maven.api.services.CoordinateFactoryRequest; +import org.apache.maven.api.services.ArtifactCoordinateFactory; +import org.apache.maven.api.services.ArtifactCoordinateFactoryRequest; import org.apache.maven.shared.utils.StringUtils; import org.eclipse.aether.artifact.ArtifactType; @@ -32,10 +32,10 @@ import static org.apache.maven.internal.impl.Utils.nonNull; @Named -public class DefaultCoordinateFactory implements CoordinateFactory +public class DefaultArtifactCoordinateFactory implements ArtifactCoordinateFactory { @Override - public Coordinate create( @Nonnull CoordinateFactoryRequest request ) + public ArtifactCoordinate create( @Nonnull ArtifactCoordinateFactoryRequest request ) { nonNull( request, "request can not be null" ); DefaultSession session = cast( DefaultSession.class, request.getSession(), @@ -49,7 +49,7 @@ public Coordinate create( @Nonnull CoordinateFactoryRequest request ) ? request.getClassifier() : type != null ? type.getClassifier() : ""; String extension = StringUtils.isNotEmpty( request.getExtension() ) ? request.getExtension() : type != null ? type.getExtension() : ""; - return new DefaultCoordinate( + return new DefaultArtifactCoordinate( session, new org.eclipse.aether.artifact.DefaultArtifact( request.getGroupId(), diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java index a54ea574089c..69b9f991ed1d 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactManager.java @@ -21,6 +21,7 @@ import org.apache.maven.api.annotations.Nonnull; +import java.io.File; import java.nio.file.Path; import java.util.Collection; import java.util.Collections; @@ -63,7 +64,15 @@ public Optional getPath( @Nonnull Artifact artifact ) } } Path path = paths.get( artifact ); - return path != null ? Optional.of( path ) : artifact.getPath(); + if ( path == null && artifact instanceof DefaultArtifact ) + { + File file = ( (DefaultArtifact) artifact ).getArtifact().getFile(); + if ( file != null ) + { + path = file.toPath(); + } + } + return Optional.ofNullable( path ); } @Override diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java index dd43df913f1c..dadb37acd786 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultArtifactResolver.java @@ -22,12 +22,20 @@ import org.apache.maven.api.annotations.Nonnull; import javax.inject.Inject; +import java.nio.file.Path; +import java.util.HashMap; +import java.util.List; +import java.util.Map; +import java.util.stream.Collectors; + import org.apache.maven.api.Artifact; +import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactResolver; import org.apache.maven.api.services.ArtifactResolverException; import org.apache.maven.api.services.ArtifactResolverRequest; import org.apache.maven.api.services.ArtifactResolverResult; import org.eclipse.aether.RepositorySystem; +import org.eclipse.aether.repository.RemoteRepository; import org.eclipse.aether.resolution.ArtifactRequest; import org.eclipse.aether.resolution.ArtifactResolutionException; import org.eclipse.aether.resolution.ArtifactResult; @@ -54,16 +62,25 @@ public ArtifactResolverResult resolve( ArtifactResolverRequest request ) "request.session should be a " + DefaultSession.class ); try { - ArtifactRequest req = new ArtifactRequest() - .setArtifact( session.toArtifact( request.getCoordinate() ) ) - .setRepositories( session.toRepositories( session.getRemoteRepositories() ) ); - ArtifactResult res = repositorySystem.resolveArtifact( session.getSession(), req ); + List repositories = session.toRepositories( session.getRemoteRepositories() ); + List requests = request.getCoordinates().stream() + .map( coord -> new ArtifactRequest( session.toArtifact( coord ), repositories, null ) ) + .collect( Collectors.toList() ); + List results = repositorySystem.resolveArtifacts( session.getSession(), requests ); + Map paths = new HashMap<>(); + for ( ArtifactResult result : results ) + { + Artifact artifact = session.getArtifact( result.getArtifact() ); + Path path = result.getArtifact().getFile().toPath(); + session.getService( ArtifactManager.class ).setPath( artifact, path ); + paths.put( artifact, path ); + } return new ArtifactResolverResult() { @Override - public Artifact getArtifact() + public Map getArtifacts() { - return session.getArtifact( res.getArtifact() ); + return paths; } }; } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java index be723e489ac5..78b6eaddd8e1 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependency.java @@ -19,13 +19,13 @@ * under the License. */ -import java.util.Collection; +import java.util.Objects; import org.apache.maven.api.Dependency; -import org.apache.maven.api.Exclusion; +import org.apache.maven.api.DependencyCoordinate; import org.apache.maven.api.Scope; import org.apache.maven.api.Type; -import org.apache.maven.api.VersionRange; +import org.apache.maven.api.Version; import org.apache.maven.api.annotations.Nonnull; import org.apache.maven.api.annotations.Nullable; import org.apache.maven.api.services.TypeRegistry; @@ -37,12 +37,24 @@ public class DefaultDependency implements Dependency { private final AbstractSession session; private final org.eclipse.aether.graph.Dependency dependency; + private final String key; public DefaultDependency( @Nonnull AbstractSession session, @Nonnull org.eclipse.aether.graph.Dependency dependency ) { this.session = nonNull( session, "session" ); this.dependency = nonNull( dependency, "dependency" ); + this.key = getGroupId() + + ':' + getArtifactId() + + ':' + getExtension() + + ( getClassifier().length() > 0 ? ":" + getClassifier() : "" ) + + ':' + getVersion(); + } + + @Override + public String key() + { + return key; } @Nonnull @@ -70,9 +82,9 @@ public String getClassifier() } @Override - public VersionRange getVersion() + public Version getVersion() { - return session.parseVersionRange( dependency.getArtifact().getVersion() ); + return session.parseVersion( dependency.getArtifact().getVersion() ); } @Override @@ -85,10 +97,16 @@ public String getExtension() public Type getType() { String type = dependency.getArtifact().getProperty( ArtifactProperties.TYPE, - dependency.getArtifact().getExtension() ); + dependency.getArtifact().getExtension() ); return session.getService( TypeRegistry.class ).getType( type ); } + @Override + public boolean isSnapshot() + { + return DefaultVersionParser.checkSnapshot( dependency.getArtifact().getVersion() ); + } + @Nonnull @Override public Scope getScope() @@ -98,35 +116,34 @@ public Scope getScope() @Nullable @Override - public Boolean getOptional() + public boolean isOptional() { - return dependency.getOptional(); + return dependency.isOptional(); } @Nonnull @Override - public Collection getExclusions() + public DependencyCoordinate toCoordinate() { - return new MappedCollection<>( dependency.getExclusions(), this::toExclusion ); + return session.createDependencyCoordinate( this ); } - private Exclusion toExclusion( org.eclipse.aether.graph.Exclusion exclusion ) + @Override + public boolean equals( Object o ) + { + return o instanceof DefaultDependency + && Objects.equals( key, ( (DefaultDependency) o ).key ); + } + + @Override + public int hashCode() { - return new Exclusion() - { - @Nullable - @Override - public String getGroupId() - { - return exclusion.getGroupId(); - } + return key.hashCode(); + } - @Nullable - @Override - public String getArtifactId() - { - return exclusion.getArtifactId(); - } - }; + @Override + public String toString() + { + return dependency.toString(); } } diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinate.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinate.java new file mode 100644 index 000000000000..f6b7862f0ae1 --- /dev/null +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinate.java @@ -0,0 +1,132 @@ +package org.apache.maven.internal.impl; + +/* + * 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. + */ + +import java.util.Collection; + +import org.apache.maven.api.DependencyCoordinate; +import org.apache.maven.api.Exclusion; +import org.apache.maven.api.Scope; +import org.apache.maven.api.Type; +import org.apache.maven.api.VersionRange; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.annotations.Nullable; +import org.apache.maven.api.services.TypeRegistry; +import org.eclipse.aether.artifact.ArtifactProperties; + +import static org.apache.maven.internal.impl.Utils.nonNull; + +public class DefaultDependencyCoordinate implements DependencyCoordinate +{ + private final AbstractSession session; + private final org.eclipse.aether.graph.Dependency dependency; + + public DefaultDependencyCoordinate( @Nonnull AbstractSession session, + @Nonnull org.eclipse.aether.graph.Dependency dependency ) + { + this.session = nonNull( session, "session" ); + this.dependency = nonNull( dependency, "dependency" ); + } + + @Nonnull + public org.eclipse.aether.graph.Dependency getDependency() + { + return dependency; + } + + @Override + public String getGroupId() + { + return dependency.getArtifact().getGroupId(); + } + + @Override + public String getArtifactId() + { + return dependency.getArtifact().getArtifactId(); + } + + @Override + public String getClassifier() + { + return dependency.getArtifact().getClassifier(); + } + + @Override + public VersionRange getVersion() + { + return session.parseVersionRange( dependency.getArtifact().getVersion() ); + } + + @Override + public String getExtension() + { + return dependency.getArtifact().getExtension(); + } + + @Override + public Type getType() + { + String type = dependency.getArtifact().getProperty( ArtifactProperties.TYPE, + dependency.getArtifact().getExtension() ); + return session.getService( TypeRegistry.class ).getType( type ); + } + + @Nonnull + @Override + public Scope getScope() + { + return Scope.get( dependency.getScope() ); + } + + @Nullable + @Override + public Boolean getOptional() + { + return dependency.getOptional(); + } + + @Nonnull + @Override + public Collection getExclusions() + { + return new MappedCollection<>( dependency.getExclusions(), this::toExclusion ); + } + + private Exclusion toExclusion( org.eclipse.aether.graph.Exclusion exclusion ) + { + return new Exclusion() + { + @Nullable + @Override + public String getGroupId() + { + return exclusion.getGroupId(); + } + + @Nullable + @Override + public String getArtifactId() + { + return exclusion.getArtifactId(); + } + }; + } +} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinateFactory.java similarity index 64% rename from maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java rename to maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinateFactory.java index 676cbea03d62..ae765e934301 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyFactory.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyCoordinateFactory.java @@ -23,31 +23,44 @@ import java.util.stream.Collectors; -import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; import org.apache.maven.api.Exclusion; import org.apache.maven.api.annotations.Nonnull; -import org.apache.maven.api.services.DependencyFactory; -import org.apache.maven.api.services.DependencyFactoryRequest; +import org.apache.maven.api.services.DependencyCoordinateFactory; +import org.apache.maven.api.services.DependencyCoordinateFactoryRequest; +import org.eclipse.aether.artifact.ArtifactType; import static org.apache.maven.internal.impl.Utils.cast; import static org.apache.maven.internal.impl.Utils.nonNull; @Named -public class DefaultDependencyFactory implements DependencyFactory +public class DefaultDependencyCoordinateFactory implements DependencyCoordinateFactory { @Nonnull @Override - public Dependency create( @Nonnull DependencyFactoryRequest request ) + public DependencyCoordinate create( @Nonnull DependencyCoordinateFactoryRequest request ) { nonNull( request, "request can not be null" ); DefaultSession session = cast( DefaultSession.class, request.getSession(), "request.session should be a " + DefaultSession.class ); - return new DefaultDependency( + ArtifactType type = null; + if ( request.getType() != null ) + { + type = session.getSession().getArtifactTypeRegistry().get( request.getType() ); + } + return new DefaultDependencyCoordinate( session, new org.eclipse.aether.graph.Dependency( - session.toArtifact( request.getCoordinate() ), + new org.eclipse.aether.artifact.DefaultArtifact( + request.getGroupId(), + request.getArtifactId(), + request.getClassifier(), + request.getExtension(), + request.getVersion(), + type + ), request.getScope(), request.isOptional(), request.getExclusions().stream().map( this::toExclusion ).collect( Collectors.toList() ) ) ); diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java deleted file mode 100644 index c042608e873c..000000000000 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultDependencyResolver.java +++ /dev/null @@ -1,107 +0,0 @@ -package org.apache.maven.internal.impl; - -/* - * 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. - */ - -import javax.inject.Inject; -import javax.inject.Named; - -import java.util.List; -import java.util.function.Predicate; - -import org.apache.maven.api.Node; -import org.apache.maven.api.services.ArtifactResolverResult; -import org.apache.maven.api.services.DependencyResolver; -import org.apache.maven.api.services.DependencyResolverException; -import org.apache.maven.api.services.DependencyResolverRequest; -import org.apache.maven.api.services.DependencyResolverResult; -import org.eclipse.aether.RepositorySystem; -import org.eclipse.aether.collection.CollectRequest; -import org.eclipse.aether.graph.DependencyFilter; -import org.eclipse.aether.resolution.DependencyRequest; -import org.eclipse.aether.resolution.DependencyResolutionException; -import org.eclipse.aether.resolution.DependencyResult; - -@Named -public class DefaultDependencyResolver implements DependencyResolver -{ - - private final RepositorySystem repositorySystem; - - @Inject - DefaultDependencyResolver( RepositorySystem repositorySystem ) - { - this.repositorySystem = repositorySystem; - } - - @Override - public DependencyResolverResult resolve( DependencyResolverRequest request ) - throws DependencyResolverException - { - DefaultSession session = ( DefaultSession ) request.getSession(); - - CollectRequest collectRequest = new CollectRequest() - .setRootArtifact( request.getRootArtifact().map( session::toArtifact ).orElse( null ) ) - .setRoot( request.getRoot().map( session::toDependency ).orElse( null ) ) - .setDependencies( session.toDependencies( request.getDependencies() ) ) - .setManagedDependencies( session.toDependencies( request.getManagedDependencies() ) ) - .setRepositories( session.toRepositories( request.getSession().getRemoteRepositories() ) ); - DependencyFilter filter = request.getFilter() - .map( f -> toDependencyFilter( session, f ) ) - .orElse( null ); - DependencyRequest dependencyRequest = new DependencyRequest() - .setCollectRequest( collectRequest ) - .setFilter( filter ); - - try - { - DependencyResult result = repositorySystem.resolveDependencies( session.getSession(), dependencyRequest ); - return new DependencyResolverResult() - { - @Override - public List getCollectorExceptions() - { - return result.getCollectExceptions(); - } - - @Override - public Node getRoot() - { - return session.getNode( result.getRoot() ); - } - - @Override - public List getArtifactResults() - { - return new MappedList<>( result.getArtifactResults(), - ar -> () -> session.getArtifact( ar.getArtifact() ) ); - } - }; - } - catch ( DependencyResolutionException e ) - { - throw new DependencyResolverException( "Unable to resolve dependencies", e ); - } - } - - private DependencyFilter toDependencyFilter( DefaultSession session, Predicate filter ) - { - return ( node, parents ) -> filter.test( session.getNode( node ) ); - } -} diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java index 8da774390e97..787d76c22f78 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultNode.java @@ -24,7 +24,6 @@ import java.util.Objects; import java.util.Optional; -import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; import org.apache.maven.api.Node; import org.apache.maven.api.RemoteRepository; @@ -55,12 +54,6 @@ DependencyNode getDependencyNode() return node; } - @Override - public Artifact getArtifact() - { - return node.getArtifact() != null ? session.getArtifact( node.getArtifact() ) : null; - } - @Override public Dependency getDependency() { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java index 05a22b7c774c..50e083dd0b6c 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProject.java @@ -35,7 +35,7 @@ import org.apache.maven.RepositoryUtils; import org.apache.maven.api.Artifact; -import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; import org.apache.maven.api.Exclusion; import org.apache.maven.api.Project; import org.apache.maven.api.model.DependencyManagement; @@ -122,14 +122,14 @@ public Optional getPomPath() @Nonnull @Override - public List getDependencies() + public List getDependencies() { return new MappedList<>( getModel().getDependencies(), this::toDependency ); } @Nonnull @Override - public List getManagedDependencies() + public List getManagedDependencies() { DependencyManagement dependencyManagement = getModel().getDependencyManagement(); if ( dependencyManagement != null ) @@ -165,9 +165,9 @@ public List getRemotePluginRepositories() } @Nonnull - private Dependency toDependency( org.apache.maven.api.model.Dependency dependency ) + private DependencyCoordinate toDependency( org.apache.maven.api.model.Dependency dependency ) { - return new Dependency() + return new DependencyCoordinate() { @Override public String getGroupId() diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java index 73e6a3a5311b..d9911c20148d 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultProjectBuilder.java @@ -19,8 +19,6 @@ * under the License. */ -import org.apache.maven.api.Coordinate; -import org.apache.maven.api.annotations.Nonnull; import javax.inject.Inject; import java.io.File; @@ -28,15 +26,23 @@ import java.io.InputStream; import java.nio.file.Path; import java.util.Collection; -import java.util.Collections; import java.util.List; import java.util.Optional; import org.apache.maven.RepositoryUtils; import org.apache.maven.api.Artifact; +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.api.Node; import org.apache.maven.api.Project; +import org.apache.maven.api.annotations.Nonnull; +import org.apache.maven.api.services.DependencyCollectorResult; +import org.apache.maven.api.services.ProjectBuilder; +import org.apache.maven.api.services.ProjectBuilderException; +import org.apache.maven.api.services.ProjectBuilderProblem; import org.apache.maven.api.services.ProjectBuilderProblemSeverity; +import org.apache.maven.api.services.ProjectBuilderRequest; +import org.apache.maven.api.services.ProjectBuilderResult; +import org.apache.maven.api.services.ProjectBuilderSource; import org.apache.maven.artifact.DefaultArtifact; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.model.building.ModelProblem; @@ -45,14 +51,6 @@ import org.apache.maven.project.ProjectBuildingException; import org.apache.maven.project.ProjectBuildingRequest; import org.apache.maven.project.ProjectBuildingResult; -import org.apache.maven.api.services.ArtifactResolverResult; -import org.apache.maven.api.services.DependencyResolverResult; -import org.apache.maven.api.services.ProjectBuilder; -import org.apache.maven.api.services.ProjectBuilderException; -import org.apache.maven.api.services.ProjectBuilderProblem; -import org.apache.maven.api.services.ProjectBuilderRequest; -import org.apache.maven.api.services.ProjectBuilderResult; -import org.apache.maven.api.services.ProjectBuilderSource; public class DefaultProjectBuilder implements ProjectBuilder { @@ -115,10 +113,10 @@ else if ( request.getArtifact().isPresent() ) } else if ( request.getCoordinate().isPresent() ) { - Coordinate c = request.getCoordinate().get(); + ArtifactCoordinate c = request.getCoordinate().get(); org.apache.maven.artifact.Artifact artifact = new DefaultArtifact( c.getGroupId(), c.getArtifactId(), c.getVersion().asString(), null, - c.getType().getName(), c.getClassifier(), null ); + c.getExtension(), c.getClassifier(), null ); res = builder.build( artifact, request.isAllowStubModel(), req ); } else @@ -235,13 +233,13 @@ public ProjectBuilderProblemSeverity getSeverity() @Nonnull @Override - public Optional getDependencyResolverResult() + public Optional getDependencyResolverResult() { return Optional.ofNullable( res.getDependencyResolutionResult() ) - .map( r -> new DependencyResolverResult() + .map( r -> new DependencyCollectorResult() { @Override - public List getCollectorExceptions() + public List getExceptions() { return r.getCollectionErrors(); } @@ -252,11 +250,11 @@ public Node getRoot() return session.getNode( r.getDependencyGraph() ); } - @Override - public List getArtifactResults() - { - return Collections.emptyList(); - } +// @Override +// public List getArtifactResults() +// { +// return Collections.emptyList(); +// } } ); } }; diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java index a223e854663b..2b4ed18ccd94 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/DefaultSession.java @@ -23,6 +23,7 @@ import java.nio.file.Paths; import java.time.Instant; import java.util.Collections; +import java.util.HashMap; import java.util.List; import java.util.Map; import java.util.NoSuchElementException; @@ -32,7 +33,7 @@ import java.util.stream.Collectors; import org.apache.maven.RepositoryUtils; -import org.apache.maven.api.Dependency; +import org.apache.maven.api.DependencyCoordinate; import org.apache.maven.api.LocalRepository; import org.apache.maven.api.Project; import org.apache.maven.api.RemoteRepository; @@ -46,10 +47,9 @@ import org.apache.maven.api.services.ArtifactInstaller; import org.apache.maven.api.services.ArtifactManager; import org.apache.maven.api.services.ArtifactResolver; -import org.apache.maven.api.services.CoordinateFactory; +import org.apache.maven.api.services.ArtifactCoordinateFactory; import org.apache.maven.api.services.DependencyCollector; -import org.apache.maven.api.services.DependencyFactory; -import org.apache.maven.api.services.DependencyResolver; +import org.apache.maven.api.services.DependencyCoordinateFactory; import org.apache.maven.api.services.LocalRepositoryManager; import org.apache.maven.api.services.Lookup; import org.apache.maven.api.services.MavenException; @@ -93,12 +93,11 @@ public class DefaultSession extends AbstractSession private final org.apache.maven.project.ProjectBuilder projectBuilder; private final MavenRepositorySystem mavenRepositorySystem; private final DefaultToolchainManagerPrivate toolchainManagerPrivate; - private final ArtifactManager artifactManager; - private final ProjectManager projectManager; private final PlexusContainer container; private final MojoExecutionScope mojoExecutionScope; private final RuntimeInformation runtimeInformation; private final ArtifactHandlerManager artifactHandlerManager; + private final Map, Service> services = new HashMap<>(); @SuppressWarnings( "checkstyle:ParameterNumber" ) public DefaultSession( @Nonnull MavenSession session, @@ -125,9 +124,32 @@ public DefaultSession( @Nonnull MavenSession session, this.container = container; this.mojoExecutionScope = mojoExecutionScope; this.runtimeInformation = runtimeInformation; - this.artifactManager = new DefaultArtifactManager( this ); - this.projectManager = new DefaultProjectManager( this, artifactManager, container ); this.artifactHandlerManager = artifactHandlerManager; + + ArtifactManager artifactManager = new DefaultArtifactManager( this ); + ProjectManager projectManager = new DefaultProjectManager( this, artifactManager, container ); + + services.put( ArtifactFactory.class, new DefaultArtifactFactory() ); + services.put( ArtifactResolver.class, new DefaultArtifactResolver( repositorySystem ) ); + services.put( ArtifactDeployer.class, new DefaultArtifactDeployer( repositorySystem ) ); + services.put( ArtifactInstaller.class, new DefaultArtifactInstaller( repositorySystem ) ); + services.put( ArtifactManager.class, artifactManager ); + services.put( DependencyCoordinateFactory.class, new DefaultDependencyCoordinateFactory() ); + services.put( DependencyCollector.class, new DefaultDependencyCollector( repositorySystem ) ); + services.put( ProjectBuilder.class, new DefaultProjectBuilder( projectBuilder ) ); + services.put( ProjectManager.class, projectManager ); + services.put( LocalRepositoryManager.class, new DefaultLocalRepositoryManager() ); + services.put( RepositoryFactory.class, new DefaultRepositoryFactory( repositorySystem ) ); + services.put( ToolchainManager.class, new DefaultToolchainManager( toolchainManagerPrivate ) ); + services.put( ModelXmlFactory.class, new DefaultModelXmlFactory() ); + services.put( SettingsXmlFactory.class, new DefaultSettingsXmlFactory() ); + services.put( ToolchainsXmlFactory.class, new DefaultToolchainsXmlFactory() ); + services.put( Prompter.class, new DefaultPrompter( container ) ); + services.put( MessageBuilderFactory.class, new DefaultMessageBuilderFactory() ); + services.put( VersionParser.class, new DefaultVersionParser() ); + services.put( ArtifactCoordinateFactory.class, new DefaultArtifactCoordinateFactory() ); + services.put( TypeRegistry.class, new DefaultTypeRegistry( artifactHandlerManager ) ); + services.put( Lookup.class, new DefaultLookup( container ) ); } public MavenSession getMavenSession() @@ -300,95 +322,12 @@ public Session withRemoteRepositories( @Nonnull List repositor @SuppressWarnings( "unchecked" ) public T getService( Class clazz ) throws NoSuchElementException { - if ( clazz == ArtifactFactory.class ) - { - return (T) new DefaultArtifactFactory(); - } - else if ( clazz == ArtifactResolver.class ) - { - return (T) new DefaultArtifactResolver( repositorySystem ); - } - else if ( clazz == ArtifactDeployer.class ) - { - return (T) new DefaultArtifactDeployer( repositorySystem ); - } - else if ( clazz == ArtifactInstaller.class ) - { - return (T) new DefaultArtifactInstaller( repositorySystem ); - } - else if ( clazz == ArtifactManager.class ) - { - return (T) artifactManager; - } - else if ( clazz == DependencyFactory.class ) - { - return (T) new DefaultDependencyFactory(); - } - else if ( clazz == DependencyCollector.class ) - { - return (T) new DefaultDependencyCollector( repositorySystem ); - } - else if ( clazz == DependencyResolver.class ) - { - return (T) new DefaultDependencyResolver( repositorySystem ); - } - else if ( clazz == ProjectBuilder.class ) - { - return (T) new DefaultProjectBuilder( projectBuilder ); - } - else if ( clazz == ProjectManager.class ) - { - return (T) projectManager; - } - else if ( clazz == LocalRepositoryManager.class ) - { - return (T) new DefaultLocalRepositoryManager(); - } - else if ( clazz == RepositoryFactory.class ) - { - return (T) new DefaultRepositoryFactory( repositorySystem ); - } - else if ( clazz == ToolchainManager.class ) - { - return (T) new DefaultToolchainManager( toolchainManagerPrivate ); - } - else if ( clazz == ModelXmlFactory.class ) - { - return (T) new DefaultModelXmlFactory(); - } - else if ( clazz == SettingsXmlFactory.class ) - { - return (T) new DefaultSettingsXmlFactory(); - } - else if ( clazz == ToolchainsXmlFactory.class ) - { - return (T) new DefaultToolchainsXmlFactory(); - } - else if ( clazz == Prompter.class ) - { - return (T) new DefaultPrompter( container ); - } - else if ( clazz == MessageBuilderFactory.class ) - { - return (T) new DefaultMessageBuilderFactory(); - } - else if ( clazz == VersionParser.class ) - { - return (T) new DefaultVersionParser(); - } - else if ( clazz == CoordinateFactory.class ) - { - return (T) new DefaultCoordinateFactory(); - } - else if ( clazz == TypeRegistry.class ) - { - return (T) new DefaultTypeRegistry( artifactHandlerManager ); - } - else if ( clazz == Lookup.class ) + T t = (T) services.get( clazz ); + if ( t == null ) { - return (T) new DefaultLookup( container ); + throw new NoSuchElementException( clazz.getName() ); } - throw new NoSuchElementException( clazz.getName() ); + return t; } @Nonnull @@ -435,11 +374,11 @@ public ArtifactRepository toArtifactRepository( RemoteRepository repository ) } } - public org.eclipse.aether.graph.Dependency toDependency( Dependency dependency ) + public org.eclipse.aether.graph.Dependency toDependency( DependencyCoordinate dependency ) { - if ( dependency instanceof DefaultDependency ) + if ( dependency instanceof DefaultDependencyCoordinate ) { - return ( (DefaultDependency) dependency ).getDependency(); + return ( (DefaultDependencyCoordinate) dependency ).getDependency(); } else { diff --git a/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java b/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java index dd0e91abaa19..066df38fa423 100644 --- a/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java +++ b/maven-core/src/main/java/org/apache/maven/internal/impl/WrapperNode.java @@ -22,7 +22,6 @@ import java.util.List; import java.util.Optional; -import org.apache.maven.api.Artifact; import org.apache.maven.api.Dependency; import org.apache.maven.api.Node; import org.apache.maven.api.RemoteRepository; @@ -53,12 +52,6 @@ public List getChildren() return children; } - @Override - public Artifact getArtifact() - { - return delegate.getArtifact(); - } - @Override public Dependency getDependency() { diff --git a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java index 43f1e9564d3a..e8327783df46 100644 --- a/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java +++ b/maven-core/src/test/java/org/apache/maven/AbstractCoreMavenComponentTestCase.java @@ -22,11 +22,13 @@ import java.io.File; import java.util.ArrayList; import java.util.Arrays; +import java.util.Collections; import java.util.List; import java.util.Properties; import org.apache.maven.artifact.Artifact; import org.apache.maven.artifact.InvalidRepositoryException; +import org.apache.maven.artifact.handler.manager.DefaultArtifactHandlerManager; import org.apache.maven.artifact.repository.ArtifactRepository; import org.apache.maven.execution.DefaultMavenExecutionRequest; import org.apache.maven.execution.DefaultMavenExecutionResult; @@ -170,7 +172,7 @@ protected MavenSession createMavenSession( File pom, Properties executionPropert session.setAllProjects( session.getProjects() ); session.setSession( new DefaultSession( session, new DefaultRepositorySystem(), null, null, null, null, null, null, - null, null ) ); + null, new DefaultArtifactHandlerManager( Collections.emptyMap() ) ) ); return session; } diff --git a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java index 49be1709226d..f707b543943e 100644 --- a/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java +++ b/maven-core/src/test/java/org/apache/maven/internal/impl/TestApi.java @@ -21,13 +21,13 @@ import javax.inject.Inject; -import java.nio.file.Paths; +import java.nio.file.Path; import java.util.Collections; +import java.util.Optional; -import org.apache.maven.api.Coordinate; +import org.apache.maven.api.ArtifactCoordinate; import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager; import org.apache.maven.execution.DefaultMavenExecutionRequest; -import org.apache.maven.execution.MavenExecutionRequest; import org.apache.maven.execution.MavenSession; import org.apache.maven.api.Project; import org.apache.maven.api.Session; @@ -35,7 +35,6 @@ import org.apache.maven.api.Node; import org.apache.maven.api.services.ProjectBuilder; import org.apache.maven.api.services.ProjectBuilderRequest; -import org.apache.maven.api.services.RepositoryFactory; import org.apache.maven.bridge.MavenRepositorySystem; import org.apache.maven.execution.scope.internal.MojoExecutionScope; import org.apache.maven.repository.internal.MavenRepositorySystemUtils; @@ -109,14 +108,15 @@ void setup() @Test void testCreateAndResolveArtifact() throws Exception { - Coordinate coord = session.createCoordinate( "org.codehaus.plexus", "plexus-utils", "1.4.5", "pom" ); + ArtifactCoordinate coord = session.createArtifactCoordinate( "org.codehaus.plexus", "plexus-utils", "1.4.5", "pom" ); Artifact resolved = session.resolveArtifact( coord ); - assertTrue( resolved.getPath().isPresent() ); - assertNotNull( resolved.getPath().get() ); + Optional op = session.getArtifactPath( resolved ); + assertTrue( op.isPresent() ); + assertNotNull( op.get() ); Project project = session.getService( ProjectBuilder.class ).build( - ProjectBuilderRequest.builder().session( session ).path( resolved.getPath().get() ) + ProjectBuilderRequest.builder().session( session ).path( op.get() ) .processPlugins( false ).resolveDependencies( false ).build() ) .getProject().get(); assertNotNull( project );

a3l?*fiaBd55EAbT_h7tg{d?!VIwRKtEQTJ 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 VAZS8C=>UJC4N*{R5x0(@{0ANRw+{dS literal 0 HcmV?d00001 diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.md5 new file mode 100644 index 000000000000..291ffea0e4fc --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.md5 @@ -0,0 +1 @@ +556231599b5413a7c1f16a5fd15be574 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.sha1 new file mode 100644 index 000000000000..b8ef047d7dc3 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.jar.sha1 @@ -0,0 +1 @@ +91410b971f9659f76b0ff26a97b9fbac5de2f69e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom new file mode 100644 index 000000000000..f8b070541514 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom @@ -0,0 +1,98 @@ + + 4.0.0 + + org.codehaus.plexus + plexus-containers + 1.0-alpha-32 + + plexus-container-default + Default Plexus Container + 1.0-alpha-32 + + + + maven-surefire-plugin + + once + + **/Test*.java + **/Abstract*.java + + + + + shade-maven-plugin + org.codehaus.mojo + 1.0-alpha-9 + + + package + + shade + + + + + classworlds:classworlds + junit:junit + jmock:jmock + org.codehaus.plexus:plexus-classworlds + org.codehaus.plexus:plexus-utils + + + + + + + + + + + org.codehaus.plexus + plexus-component-api + + + org.codehaus.plexus + plexus-utils + + + org.codehaus.plexus + plexus-classworlds + + + jmock + jmock + 1.0.1 + test + + + + + + + maven-pmd-plugin + + + maven-javadoc-plugin + + + http://java.sun.com/j2ee/1.4/docs/api + http://java.sun.com/j2se/1.5.0/docs/api + http://jakarta.apache.org/commons/collections/apidocs-COLLECTIONS_3_0/ + http://jakarta.apache.org/commons/dbcp/apidocs/ + http://jakarta.apache.org/commons/fileupload/apidocs/ + http://jakarta.apache.org/commons/httpclient/apidocs/ + http://jakarta.apache.org/commons/logging/apidocs/ + http://jakarta.apache.org/commons/pool/apidocs/ + http://www.junit.org/junit/javadoc/ + http://logging.apache.org/log4j/docs/api/ + http://jakarta.apache.org/regexp/apidocs/ + http://jakarta.apache.org/velocity/api/ + + + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.md5 new file mode 100644 index 000000000000..3b237719bf5d --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.md5 @@ -0,0 +1 @@ +af4ca0022b674405556b3f397e375adc \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.sha1 new file mode 100644 index 000000000000..00b60872ed19 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-container-default/1.0-alpha-32/plexus-container-default-1.0-alpha-32.pom.sha1 @@ -0,0 +1 @@ +8f4d09d36a2345a39301dbd77ef9906c795887f7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom new file mode 100644 index 000000000000..1e8675857945 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom @@ -0,0 +1,49 @@ + + 4.0.0 + + org.codehaus.plexus + plexus + 1.0.9 + + org.codehaus.plexus + plexus-containers + pom + Parent Plexus Container POM + 1.0-alpha-16 + + plexus-component-api + plexus-container-default + + + scm:svn:http://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-16 + scm:svn:https://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-16 + http://fisheye.codehaus.org/browse/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-16 + + + + junit + junit + + compile + + + + + + org.codehaus.plexus + plexus-classworlds + 1.2-alpha-7 + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-16 + + + org.codehaus.plexus + plexus-utils + 1.3 + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.md5 new file mode 100644 index 000000000000..3db22e20eb81 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.md5 @@ -0,0 +1 @@ +3eee2016e3e307618048e30f088b546e \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.sha1 new file mode 100644 index 000000000000..3eb3627146ee --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-16/plexus-containers-1.0-alpha-16.pom.sha1 @@ -0,0 +1 @@ +46b79dd7d6a8130d2fa81c80b16b695d491548fe \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom new file mode 100644 index 000000000000..8e94894a4272 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom @@ -0,0 +1,49 @@ + + 4.0.0 + + org.codehaus.plexus + plexus + 1.0.11 + + org.codehaus.plexus + plexus-containers + pom + Parent Plexus Container POM + 1.0-alpha-32 + + plexus-component-api + plexus-container-default + + + scm:svn:http://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-32 + scm:svn:https://svn.codehaus.org/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-32 + http://fisheye.codehaus.org/browse/plexus/plexus-containers/tags/plexus-containers-1.0-alpha-32 + + + + junit + junit + 4.13.1 + compile + + + + + + org.codehaus.plexus + plexus-classworlds + 1.2-alpha-10 + + + org.codehaus.plexus + plexus-utils + 1.4.5 + + + org.codehaus.plexus + plexus-component-api + 1.0-alpha-32 + + + + diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.md5 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.md5 new file mode 100644 index 000000000000..41815f084a76 --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.md5 @@ -0,0 +1 @@ +8ac33e07134648d37e2b1253286889a7 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.sha1 b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.sha1 new file mode 100644 index 000000000000..4126071626cf --- /dev/null +++ b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-containers/1.0-alpha-32/plexus-containers-1.0-alpha-32.pom.sha1 @@ -0,0 +1 @@ +8486ff9b37d1ade2a4524c6fee72d394f88fbe08 \ No newline at end of file diff --git a/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar b/maven-core/src/test/resources/apiv4-repo/org/codehaus/plexus/plexus-utils/1.0.4/plexus-utils-1.0.4.jar new file mode 100644 index 0000000000000000000000000000000000000000..a2013d4705812441f5a8270894859d553eba50b3 GIT binary patch literal 163803 zcmagG1CZz5*6-b#wmEIvcK5XXYumQ%Y1_7K+qP|E+IHVL?|II1?^{pZ|4jwEDr+U# zshzB~Kl_`=Nr8ev1O02_z?WwJ{|f)Lg8I9a5m6GLl>ms+%l(%bBoO;wGYdI=i1NR? z@qmGVQ2$Re83BNVsEDExos4KytN?TX1ER>Y-zFhOsG1r3l~TJ|pMsgarXbT$9-|}^ zlIMGQQLEj;<$KO^NLk_lIaoaF%kQj-K{^S}i7p#Epq~ATAV%<87!GP)3J~H5SF$^u zGjQP|aJx)2BwE_en_mw)NFgsaSK z7I&pjnB`r-vCv9B76G5=IG^gR#A{QdqV?SbX>^Adp#Q1c|GWiYf9q!JVEW&+|DP6c z|7BrlYh-Mu@9g*wrvJK8|2o)zo7!0!yZxgF=KsaR*~#4MA5Mh(Pi}73|JxN3h#Xg% z`3-55uml1KC=w9}i2eWR>R{~Tt!* zHsJ8vP7sR44>28)V}cYZT}4PxToCKRp-ezQp^5VXPj8^U;|dS5amgdB$+fCU#j2^f zIqDHYY@|1O*dAvjj2U+XbL4Nq{sZO%WAWtk>F~m(VM@<;^j-VuJ^Q4KXUB8&{rh#v zRxV6O3uezS6vCb}5SnI;h|ok`nkf*t&|f?xmsoi!YbIhWbS&I{sB&~p8CTV)jx53% zH)iamb<}m_VR6Hw5c->IYth`eh?x& zQPF`2W)IB$3H&~;z2$)<=Ypv{>`rYx##YcjTCX(QETSu5^0mc`<7YnHl(#64qTo3A{OAb`!HB+K#2 z!N1UjhHd|Dr422mG-ORR+DUdT_iYCQ~1zAGW}HCxqX%#Z2_PE|ccw%j9|p0I<% z`u;t*m?XApjv`$jLf+sZHLR}=%R;NaKI4b`+hH!Ane1MwYw|K-LV z3mrj4M(L~B*)QgVk`mJr(J`OH?<-s@s2|^CCv@EM=-v0x3?i-pO4@_d$>lsT3AP+X za|;KN34m33Qxbu#?H=B|WXr=rbwCxD``2*w)dsHKLGyxnxss4n{yQ>e5XOfejgtKh+KWdr4Jp2R3Nc(rKrSAtTHZEg$4_pr{RQcj{Pj|BGCjl zFXYAoE#6S7FC<_k%{@Gs34!-EE{|jtzPVr6JqPbMK&F?k0URNWzorHWWu^k#1%Z9% zL9+#aWz{s;URRvT3Bed*M4Sg60@k%#Pw$EX9gh*1! zmm%~>CaB_u!m2Vu23z5p5J>AMQ+&#G{`Fh$S_W?_ue*11Y!O84G~3U^A}>zTEbrY~ zsTWwKAtwo6&tb5lk0lA=sxk}9s~)jAWyD-JNXx;OlCho zhdP$+r4Y_%3Cn99Jf|@)^nozODHsx1pt=8eI(wVR3V~t@DkF*itRd(FQ7F7XaEc5q z!_I5`z%B6k(8OC_&sZ2GZ*e#x^xQk&gTK-vr*xZ~E5OI%YT`F7 z5{GjC<6Tyw=_5jv_QD-Qf=u zls+x7fnYbsnA(cOu-VdTTAWrpxGf8JP>3}Lt|=kS(>tFH!Irh*BXpWJ%6973Eiuy~ zRKiZ_6x}|XPRSJZ(<{r1;u=K<+uE&83Hk1+`K|&%#=C0wJf%@xq3jJ}Es4Df32mXd z5Gk}fJnUQ9a8!j4^|X6bLi2!9lMD<`6xVe2(gE5B)I&wRKLiLjisx6R z7YjYPBy4K}j+2k{uN!bU{WTGSXLp^Dqq<6Xu8T0nImY$oEGqDqghy8`rSj3>uGJRn zP2XP~zt##p_H8MD@6^eD;Z5Oe*exKalsK=p2HEB0bhzi-jOdJ+(lpTTuvysV573+W zcIP(XOhyZ`P7N54!hED|4&qJl5MkFV@VB`0r>J~*zrBhTAIqNh<-7`h^&j7=K3(@|T;o^1@UH>BloN|FXDp*|g=W#eA^wx>Kmt+xjr|4>bN)dvKtOhAKtMGA6#Es8 zt&9zwY#o&UrXG&}4){fCFm_5ym|tHF9cwF70V6*^kV1JT0}v6_4)cBkqrw8i%GRZl zwn?D(+iXHa&1+QL3Q(epRONzzq?dE-8-k1{YW!K1F9BrfR~lAS)s#1JXy7+3rTd(0 zZ^`rvrMfUVKJ$OS?wox0c-rWEJe?8S<$*kd%SG1W57d(Nign?`)q>m<$kS(loCcVD zhPu@)hd6tbh+J2$#FVPo%yp^(RkhAXv?jxO#zE%d$G^qR$H1k3egavyoQ){!XyNwi z1wL+z%6$If_cRJ>u!WK=H@qz#e^U!s!U2#{X=+xoeHF&XC68-V z43*0c?@P6bOQRf0#|RUT!GKlA&l`idq9uX7F2$89CusBxhtosVm=l)RI#=>-*3;m` zoI0nU0ocTl{q+)(GEeVD~4{?wKhX zTQlK>vB_}9DSD*!Zk$t`-vAKxB*Tm{hd78GQ_MX%8`-%9vp&T0sWNLVs?3PuBdzpQ z;$22Ag_pCk=9#z&+wbSI8gL7DJA<2@_?TpOT{#@{;Wmr3o~w7%*SNo=S<}nV^m)P- zv8r+MRmh1g8=8|VZJkdosMiZw8;f8sEhCHa;S!PEtO`Ji@D+}XIH>`K7D+nt6FQiW zb!JSHWb=OZX^~Y8`EeDr(s<-0abN80ug_7!0GLLQ-<=~DB>O8=|`Lwm5W4jq4>IZ}Dp3PMz2l&k%QpbFxe3Ra68qMcRwSLuG&e)+WB@ zK8kfu7N&h2^o zIz=JrYq&4s2rB$UZmvYStS=C9GEX6>PQNSfH1!eZ5hwVYm3#aU!(T%y!Id zn5hxB;L|HHIeHBk{H(P0Ueo-lT9h0y}YZ#<=JbK&*Nr$=}nvZHIF<}TcawL9C*#32qX`wB*|hdm3QI<^lgx{J@Li)H zktc*5KfH6VOW~uV)zwiV&VXwZF=y1Zwe^yw$`v2j%2y?`*o)-G9FQ28p}cvCFU}Pp`0C@rf267B0@1-@{5AF5C5Q(t>!uxBkh40rW%hEGZ^7{R zVn}+y^6kk$GU)6q@EY@_T`Ut*)l7KPZjgdKW!83=z@{Ce<7OV<^o)Xgf)e?yD$x$oRJ;7^I(}FL@mwF+L+Xd zcjp7$lf-!p`}{)T0Kg5pE|foXYI<+~YN2r1LmRn{2$#fj)uzw`pD*`|Ja>u3ymRf{ z!J92FrftiRLP!aDtoJ*DP32qI_=O^X#-x>}#k>NW?ibuu>Kt@8$-`Vbl8wMzGp(Hh zVANGzo~$CKpQ5Cgq^GgFGhF^$zdzk`*CaDK1#)QfnPpkLy1IK6!dqYfbtbeGTUlk6 z;ajk;$C{AnnWFQEId}xt{19S$7PI=((~uWam&9*^;yZr(7HN3Lx$!C$y`qX!Q^TpV zW7qjLkar4VYqUz?Zz;S7eydmER;T!}N(+3EL~uoZtv@zEJdYt89tObtU1CH4FNLHN zo5w*la8rzWK#S=&W6aW>=y*d<*|(w)Y+IxyJRGV?MM804^gEN9*f>8jSwew|@G3gt zmPv$c)G3V=W7H~*FhWAR&r+XPHA<^xR3twBb)GC`R8*bfvR=Gd&Z1&*ysKV`%cu<} z5$(>uGO?gu^6S?&cH>R;;@Ep4r>Im;7^&{;y6Qa1_i@srrg{m_e7+a5@@Jtknv_;l zY#m-0T!X|9V`^DbcuFBm^`5~9*z#D(0Gu+G z(J}$dSVeDUf|9$xOXuJ673}EPih68@Cv+@xG$`kq7glUW#*a2b*k1u!<&`L}tVdoP zp)Mp5rs;QWg21X2X5iG(7k#VxZwk=5XU<5(rJ%E)76dKP>dJ1QnTYS`)KL&13$_HyWmNu)czHdtmq zSmtkBQf&YNPe%`=)Dl!{sifI`w$3!u#J4zFq4*Dpym!`Q+_h#VEnj5Ck zr)|USyxtM}np@h$+m6|RakfTMT}d8!L`oTrPVv0knS51h$g6Niu118Ecw5<4;_$>5 zRp#)7pM^6PeMtF{d1q(L$%TYPtsew zE8-_c6bV6Z zz@6ty&^RsK#a758El>RpK-vS8+Y)RCJM_vgDHL1{6Wbw3 zElk-65?l#Opq+-=TrF6_bM$r$3HV$Ljw5UXX+gmd41a=ReSs|+j(E464RrRy=Uw&u z?{xlOD6dGRJmd}*2q+W-2#EBb(s>a#JAE6Yf9LU0sxV$kM@io~lLyn%HUwZGu#oT+ zOk*U2)uGNe@{kI7glfMGW6RkSu$h?BxTiPua;X(2-n3S1R%}GP6s+x3spYcN>ROx7 zH8kH>`Dnb?T`XH<-`A~OJ7_<1xDyDW0kLd(H#M6L%#*@fQXZ zkp}B@Q$QsjTLmGUUt9f3h(oDnOy!i!gj2{Luhcc_+W_q8A)uP{>-D&;tcS8t2#1X#pLhz}l z{($=!?DGHk(&^ZRCUe#@wQgFU2W*Tx4eL-rqG$GbjiU!Et;n%#r zBv`05WEn9_xycSbIaOO5a=A(@PuUg_>^U1At(7;SnRnh7;V!ku%2plbv1gsMYtyEB zGW960ZRU1tPi-s%=`ODe*=$R;kFf zGr%slDjm&9Eo=PYjh7K?qdv1K*ON7tl=`k^8lm^}^InpNokR1&%A+GoRm>>s<9CvT zW%+c>H~*kiy1bM+){_fsyJ^-zYZ43oy;EBXo{qq?mWjDVU=uj+UiMe`9rr6s6;xqn zq)_GBAJq1Fo9}QhkBWBM>)ULmX%OnBAZbhJ2V6p|%gVJeX?9yTTa6%?&Oqu{@qi9M;W2UTnac8cqU-OBn zlLcZ)GRyXcDr_c?wa{yayluskDa_KGis+?-4ID~jB$<>jq&DISlvBv)(v~gt<0V?- zq+2o);t`ZpiBe?NR+hGm7OU<6Hxug_XDjvsiTymPy@KQ0@+g33c-xu__u5@oUVkyR zE!Sgjn$BnNmQ0%4rQ!PN`|YO!6kB1^@4sCbw#Fr@%#bLJF3ghNid^1Ay4LkiCY3(z zg9i_N)WzFdW0h>$7NxSs+k|#WJ3SZ(L4B*Z$SO&Gb|&b-8jbD2S7eG7<$x3A3Z=NQ zix%92!1Cb5s%pIkMGdRN%TIJi!1_pAmk|Ny(WTb#ye{s-!R4j0He$7%!2xBfRgX@^ zK4SSY8@tDJUUeVp5#53cuI|zzA6;)b5=2w7Acgj6tv15L$i}0ya_<&+IrV86;g%kttwy{K#r*Jy|g(%;IwACch>; zSj%*A$55!YYIi-dZf5#q1n@8+?rxATTjfu7ote#~^c~rPSLpORZu)6m$nqVqrxRSU z?94(lap!KCF`O?^f)kgr@Z!~>Tq^}k*#z&4bB$j#$G|bK~QB z8pCf(_3i+$G0;}Y4!Vrw?d_ijvo!KoE--h8!5ub_cK@((!|0vK#>z?$v~UXa;69;z zW;lTxpB@53!!yV8V|mXJm;#P*3D|E9sQE1H&Wu&hA4EIdr)!OW!HSts7+>gU zKRzzmJLu^N?G+Zy7~SPH{JE5b>3qK6QK z#Vo}bH3r0J0)-+DUf_oTFXzC$EuqRLcOP-q3VyyNvn6R7;ZaqD;=B_{JBn;ec$6iD zt{a89tqo_39Vxn|P(NDD@Z?QgXNlmpdaR;>mETOtGVvht=RqfiCP?chmKda>s6oq&w zL`s8w-5>f*I6mJNN>I1cJ+jFX&h;E4JX|d1^+GML1}aPC2OGD{X1f@%C=A|sJ$LzY zM=;0aSd<1QtA}@OQp3~MSR=D3eR%LCgT1AQ;*Cc0x8w~2?Mtnrf+JG5x=89F9_QB0 zR#$#f?lEV0)KnyYK>6Y4A^STIq9%#afLsi;Tbxm8ARFE3Ezbm?Ct8@8h8(Jdq<+_FHnn& z+4s6IM8!V|xkXV6B0qbNiF*e&xmkG7h}*`~Pvr9>ECU^V8h}jg|jW2d{O2(Lo4mfb%@gTEw0Mz5R_1#;v>Bsz$CUG>Z+Y(-5q4w&-<1mexfji7fFF?~G2&JJTRnRhgC z)IPk;L7S9Q6#(&iZR4hfD{;|#z7YYInHlx|#TG}*rG=>JANfk2z!vA2U0bYaN&`kr zdK-=u7R2zv%)A{~o)0lFxv&Uu37KzvzA}51P4sgnhkQ73A&mL5Q+~J! z?7OL_--b83*>oquZ;GAtU@GN9XHNspqQSQA$-S|pz0UW>P+BrkLbj^S5f z993ls(RwlfR`yLC4iSxdexTo&;DulYSpdW~TZpRk8p8h4aR zM$M>6HxyJKtb3QWN?}L$GWA0G&A30i<@^0w=FqW+H!!Q;=*0@{P6- zx?|BEVbG+`1b{>uNe1z3BotjJ_+!D^eo>oBI&RhihcvvCuRsNtpaj@AEmk>~o zit!{h9|ay?t(qS_;iJd${DS`fcbZt(EH5)bfPk>Tfq-cLsnaB?@8~3>Z%3k{Z{=+K zUxOe?O4hOqa;QEw&+|>F@~BF}Sscdny==dP1yBMA)tMeZO~QOSD&P_qlN+-Hd=v0l z!Vk2u_&=%DYrrF-Ei*-9iJl zzE8ro(af_(c35(`yy@U7QH*D5geN@BA1gS>*_^2Klhw3~HPpcc8P0yf1!|Hk{g{jFF?^rJZ@nm_I zPL+%W#=y&-*evBU9A4K&yj696@DyzvOkHFO(tptU-G)4x8cq5c8s@NEWUe6~r&cW= z#{PzJ&T#s57DsJdQ*0ms1QG@8F}vf=d!A6Qia`NuAoFVNfxFYVY;BVkw>fFA4x8B@ z>PPsqb3$!Fe=CI0Yz>07{;Gqf2!Md-{^<$%m#dJiwe?@NU}bJ&{NLk*Zkk8# zK0U-^Tnf=BnqdhP_Q)fM`{Do`5U4Om!e~SPuuCl*2T)1WR}%SranX3kJk*~D3X*Nj zjig%r6j_u(bPTni>Y!Wewa&)cEpyJ=D_6^PO^tulM%J6Cy?Y#^N!O4pPqRnfu6Le& zpTBv(#_4tW;P8*7m|(GMLS_T_VfHQct2q<+SC0Rze+04lmQCrJ-;1VBvHQPRUiM%P z?gZY@epH3ohTOWoMAP}GX7nHwAbsoY;}2|pk)wR$1P5KGyruYTm5T zlgrLttBFfo4l`3||J~qiOV9OoZm_uO&oH5|WGAAAmZFweDdQ(P45b!R=2t-?#np6i zgjJsIss_``VCydbUp_fm02o1lZ15{lgr6YQR{atHy`HlkazpIm@E2hnx6GSde@9wL zfXnghvT$_4E#|wO*s&Z{%2cbu7+@ZE`WRj=yor*EVf!d^yjd$*a^p~=i6}_|O$F*a zeLC55Tg9)3cVh&G+^LAkWu~`p%f%*wTCk8hL%Pu2Uh-r+|3+1Hxb#4L{))b^9#e;u z@{4P%u9jXz-%xvPb32)&?OF=?8#3nx3U$r;J)GOJy^VLpY` zc-~(N#`SFhP$m)#No$4BTz>6r+`Wi*$H3_Hm)<`}Q*~5ww0sT?O%+zS~QCf|;+?K+~Vc*5;z~ieOh1}s_pJJ5i!qCD7 zy4L)(=9eejywmVt9vXv)Tek$k9|WdW$@>M-KhdiPfMGaskD4g;dix1+n(ZKL@bjo( zz+h(f?-Pp!$KWL+NMViy`zE8c=rSyShH=ERCPttqiX>|V7NB1(9Rs`u<0Ay#e>A-Q zNdHcz88&^KlQMp*54lgKiIXxbHI8UfA1}^WkG9;I-P&4iZ~^wDYiiW2S4xg6@AAC# zkG{lhZ`N+xA#J_!UXhg2Fm5BIHYy^mxQQoC8MlyHH-f9sJ;G@y)Lv#HQ`Pu6_=ygn zQV!8F*(1bhxBB?CUrqZ{uwq0oXNM z$R3@fWw}s{x(MbuG8~Z*%1OwD14xXs7c#-Qr?=}Lip;5TmUCGhF2RB9x0NhHDQf9b zCB4}na>xT7coWjkHaJ=Yk~WRTOwO8&U}%X{$C;#>$I)P){U)!#Xj2>C#}AQMvMO?D zcz(yI*UK0-9(f-(k2htB84tb(G``gj|$HH;-9ACj=OG2DB~5wMkWQoJme3Gi$>7_ z4M}r##xSw976~8Sl=p)u8$XxQI9nc+f?2O%o%3BEoq4h7)*{R+y3ncW__EC>1Y*?ajWFU*?auhpLL{x&G#%kcI#bm{8ni=lAx zkMQD}Zx+?m6c89$Bj-kA3PiJRJ=qSxM^G-hoYbk>6#n%YrsZF3yHj!vPK?)=xs?MT zvFe`>sNIJc4VMc9z&CI^pZ@{K8+Cb%DXcp_*C(c(^bDZUph+p%GAEGML)*oXW z`e~8w@mw5Y_6Y(*6-55>hCbfGq=YO-=BgLa|3*nO61w*xR%>Y|Uk zo<6oJ2|dIG>Scg*&mAzSR9;(wBbj&qe5ixb&gQmseCoR(?4Zqh68!xRlRo{a*jFcI zEm1fH=0z!ztG}Mdf%)m;IboqHBhhy!33R!l*F2A{bF>Ke$>1nmqY))_G@&PQ!dZ_W z#Y?4&{@%k|Z>&q_sb={jD`M?Kt(kB&0P(yIAA$n_${;uL+E@RI`W4EQ$teHBvj+sG zWXAoza{)V?Av2pG;FINUcVOVj<7O=&hTIR^U?4WN6Oz~kx*K=krYH3GbcN)-p1Iku z7d=toyFPOCy*IFm>jz1B2Za73PYhICI^iN)PT%J7LQEdx@`WZ#V5sj>!?(%4{;*O34!#EG+{U2aN z%)tzf8w4hUL=B?JSWab)oGMqY@}%GvgE2o8f+9#ml@0P`hV`@5R!NpxB`t8;$UExY z9aQzHy9!m%e-vbc!{BNW` z&VFTo*yT!+Qk$WpM2mf3iWrTs=Wlq!j}fub$P?2hWLDm`eu+s;$}P(BZbUjfR+RX6 zJi4fBQs;mH7zWp+Q$8-*zG5b=YA zmakCiwJ`PqsZzUFCo+=Dbo?cUu1jK@G2phH^QF)b2iH5C*cpZ&xHDqKO`lbnet8EG zy;cVEa7S(8lB!{IG5-jU?oRVE&6~$PD4LLf+^ii&HZsnQ-#=bdyxw?o7^96> z;n0P+t6-faZY-bf@z4@-P4lTxjZh;qEM$ONwvs?L|amxp$K&|o!Z+YLYk>C3{(uo~%w62EXn*kne2oZcr#zuecM=z| zvV@c)wYqo$0KB2!I3qH5Zgn4u9R|0Zm@)Taasu=p(I|tDULH$=d^G){BZ59x{PGXW z+?fqVxw6z9=&0w&tL%|O+S0_fUtk)}O8kMOHTiWR0^Sl8{O9}unBAm)?Y|ahtRe;r zzS@Bjtf#Ah$u=|r^adZl_#!miv6zoA2M^V05@!tSGJ7rD@v<)1 z?XD#;hgltvJB~=jb|x?hrJ&IGWVS$P)*Nq0B9dc*T+sOrPTAtt7~{LWv$ZW=1NlTx z30i|6dj5!v>D67(-0kleanNvwE!Vv|w$tp(#F&cnTf0l1<=kb@^45(ycn4+=_Ny5M zahLN2C2)u4j=Ky8RQMm<8!eY@AJG14k{*fp1l@SpyBhD|+YJA&9 z7T>@3yNC3?k#>sk4XZx_1-_ZNzHw>da_)w_BmBM{#Xf%i&{P;?PpHd1-2{{n1-uwA zX1&AO!k&F6X{G#JVd4?&yhScYjpn3JDNDTyv<>n#)=RPt`$pw*86--14XLYU-R(8crc~gN8sT+#SGy3U{s*r^8-bWRdc7sHU3NZS#?|x9 zA?WrcQ&>u`$za%|~jTy(K`KAdGV^EDgDwFS38N1ySN5UaTPo zvU+WkXu1DJ#P}Qv!=w%*p97Qi%VegECGE7ic4#48gWOgMU~E~{0zq* zO$9U8R9W;LbG)&;RVeLQCzNYEk=?5M8qILsCC?}?9p|)p6Z)Gl11~=XhXW$(W%b%` z5s!Z&7Xv{lN!7ZA_46_1?Kc@B!jCA}#DVP3kRXMNM zNsz;Vta0Wh~_? z`v(8#)+9X)=9eCud-gof%2ma|GNnM_c&3W&xSnQKP+YfcuTEiP67?goJ5@#X1AGN{ z6tS^m*|1H;<%Y$AKDp2rbIYjn+tf7={{~zQO7sBt3ndfdQK3;tn1K z46H7>Aa7W6ekd�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