├── demo ├── library-standalone-sisu │ ├── src │ │ └── test │ │ │ ├── resources │ │ │ ├── simplelogger.properties │ │ │ └── encrypted │ │ │ │ ├── settings-security.xml │ │ │ │ └── settings.xml │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── impl │ │ │ └── library │ │ │ └── ClasspathTest.java │ └── pom.xml ├── library-standalone-static │ ├── src │ │ └── test │ │ │ ├── resources │ │ │ ├── simplelogger.properties │ │ │ └── encrypted │ │ │ │ ├── settings-security.xml │ │ │ │ └── settings.xml │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── impl │ │ │ └── library │ │ │ └── ClasspathTest.java │ └── pom.xml ├── library-maven-plugin │ ├── src │ │ ├── it │ │ │ ├── model │ │ │ │ ├── invoker.properties │ │ │ │ ├── verify.groovy │ │ │ │ └── pom.xml │ │ │ ├── simple │ │ │ │ ├── invoker.properties │ │ │ │ ├── verify.groovy │ │ │ │ └── pom.xml │ │ │ ├── simple-offline │ │ │ │ ├── invoker.properties │ │ │ │ ├── verify.groovy │ │ │ │ └── pom.xml │ │ │ └── settings.xml │ │ └── main │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── impl │ │ │ └── maven │ │ │ ├── ClasspathMojo.java │ │ │ └── ModelMojo.java │ └── pom.xml ├── README.md ├── library │ ├── pom.xml │ └── src │ │ └── main │ │ └── java │ │ └── eu │ │ └── maveniverse │ │ └── maven │ │ └── mima │ │ └── impl │ │ └── library │ │ └── Classpath.java └── pom.xml ├── runtime ├── standalone-sisu │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── eu.maveniverse.maven.mima.context.Runtime │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── runtime │ │ │ └── standalonesisu │ │ │ ├── internal │ │ │ ├── Bootstrap.java │ │ │ ├── MavenSecDispatcherProvider.java │ │ │ ├── SisuLookup.java │ │ │ └── SisuBooter.java │ │ │ └── StandaloneSisuRuntime.java │ └── pom.xml ├── standalone-static │ ├── src │ │ └── main │ │ │ ├── resources │ │ │ └── META-INF │ │ │ │ └── services │ │ │ │ └── eu.maveniverse.maven.mima.context.Runtime │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── runtime │ │ │ └── standalonestatic │ │ │ ├── SettingsBuilderSupplier.java │ │ │ ├── SettingsDecrypterSupplier.java │ │ │ ├── ProfileSelectorSupplier.java │ │ │ ├── StaticLookup.java │ │ │ ├── CompatLookup.java │ │ │ └── StandaloneStaticRuntime.java │ └── pom.xml ├── standalone-shared │ ├── src │ │ └── main │ │ │ ├── filtered-resources │ │ │ └── eu │ │ │ │ └── maveniverse │ │ │ │ └── maven │ │ │ │ └── mima │ │ │ │ └── runtime │ │ │ │ └── shared │ │ │ │ └── internal │ │ │ │ └── version.properties │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── runtime │ │ │ └── shared │ │ │ └── PreBoot.java │ └── pom.xml ├── standalone-sisu-uber │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── eu │ │ │ │ └── maveniverse │ │ │ │ └── maven │ │ │ │ └── mima │ │ │ │ └── runtime │ │ │ │ └── standalonesisu │ │ │ │ └── uber │ │ │ │ └── Dummy.java │ │ └── assemblies │ │ │ └── uber-source.xml │ └── pom.xml ├── standalone-static-uber │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── eu │ │ │ │ └── maveniverse │ │ │ │ └── maven │ │ │ │ └── mima │ │ │ │ └── runtime │ │ │ │ └── standalonestatic │ │ │ │ └── uber │ │ │ │ └── Dummy.java │ │ └── assemblies │ │ │ └── uber-source.xml │ └── pom.xml ├── embedded-maven │ ├── src │ │ └── main │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── runtime │ │ │ └── maven │ │ │ ├── internal │ │ │ ├── Bootstrap.java │ │ │ └── PlexusLookup.java │ │ │ └── MavenRuntime.java │ └── pom.xml └── pom.xml ├── .mvn └── wrapper │ └── maven-wrapper.properties ├── .github ├── dependabot.yml └── workflows │ └── ci.yml ├── extensions ├── mmr │ ├── README.md │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── eu │ │ │ │ └── maveniverse │ │ │ │ └── maven │ │ │ │ └── mima │ │ │ │ └── extensions │ │ │ │ └── mmr │ │ │ │ ├── package-info.java │ │ │ │ ├── ModelResponse.java │ │ │ │ ├── ModelRequest.java │ │ │ │ ├── MavenModelReader.java │ │ │ │ └── internal │ │ │ │ └── ModelResolverImpl.java │ │ └── test │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── extensions │ │ │ └── mmr │ │ │ └── MavenModelReaderTest.java │ └── pom.xml ├── mhc4 │ ├── README.md │ ├── src │ │ ├── main │ │ │ └── java │ │ │ │ └── eu │ │ │ │ └── maveniverse │ │ │ │ └── maven │ │ │ │ └── mima │ │ │ │ └── extensions │ │ │ │ └── mhc4 │ │ │ │ ├── package-info.java │ │ │ │ └── MavenHttpClient4Factory.java │ │ └── test │ │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── extensions │ │ │ └── mhc4 │ │ │ └── MavenHttpClient4FactoryTest.java │ └── pom.xml └── pom.xml ├── .gitignore ├── context ├── src │ ├── main │ │ └── java │ │ │ └── eu │ │ │ └── maveniverse │ │ │ └── maven │ │ │ └── mima │ │ │ └── context │ │ │ ├── MavenUserHome.java │ │ │ ├── MavenSystemHome.java │ │ │ ├── Lookup.java │ │ │ ├── internal │ │ │ ├── IteratingLookup.java │ │ │ ├── MavenSystemHomeImpl.java │ │ │ └── MavenUserHomeImpl.java │ │ │ ├── HTTPProxy.java │ │ │ ├── Runtime.java │ │ │ ├── Runtimes.java │ │ │ └── Context.java │ └── test │ │ └── java │ │ └── eu │ │ └── maveniverse │ │ └── maven │ │ └── mima │ │ └── context │ │ ├── ContextOverridesTest.java │ │ └── internal │ │ └── RuntimeSupportTest.java └── pom.xml └── mvnw.cmd /demo/library-standalone-sisu/src/test/resources/simplelogger.properties: -------------------------------------------------------------------------------- 1 | org.slf4j.simpleLogger.defaultLogLevel=debug 2 | org.slf4j.simpleLogger.log.org.apache.http=warn 3 | -------------------------------------------------------------------------------- /demo/library-standalone-static/src/test/resources/simplelogger.properties: -------------------------------------------------------------------------------- 1 | org.slf4j.simpleLogger.defaultLogLevel=debug 2 | org.slf4j.simpleLogger.log.org.apache.http=warn 3 | -------------------------------------------------------------------------------- /runtime/standalone-sisu/src/main/resources/META-INF/services/eu.maveniverse.maven.mima.context.Runtime: -------------------------------------------------------------------------------- 1 | eu.maveniverse.maven.mima.runtime.standalonesisu.StandaloneSisuRuntime 2 | -------------------------------------------------------------------------------- /runtime/standalone-static/src/main/resources/META-INF/services/eu.maveniverse.maven.mima.context.Runtime: -------------------------------------------------------------------------------- 1 | eu.maveniverse.maven.mima.runtime.standalonestatic.StandaloneStaticRuntime 2 | -------------------------------------------------------------------------------- /.mvn/wrapper/maven-wrapper.properties: -------------------------------------------------------------------------------- 1 | wrapperVersion=3.3.4 2 | distributionType=only-script 3 | distributionUrl=https://repo.maven.apache.org/maven2/org/apache/maven/apache-maven/3.9.12/apache-maven-3.9.12-bin.zip 4 | -------------------------------------------------------------------------------- /demo/library-standalone-sisu/src/test/resources/encrypted/settings-security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {P8rgcUTZPzQH2RqE0DEC2iydOMk0bdnA7uyONZ6VnTQ=} 5 | 6 | -------------------------------------------------------------------------------- /demo/library-standalone-static/src/test/resources/encrypted/settings-security.xml: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | {P8rgcUTZPzQH2RqE0DEC2iydOMk0bdnA7uyONZ6VnTQ=} 5 | 6 | -------------------------------------------------------------------------------- /.github/dependabot.yml: -------------------------------------------------------------------------------- 1 | version: 2 2 | updates: 3 | 4 | - package-ecosystem: "maven" 5 | directory: "/" 6 | schedule: 7 | interval: "daily" 8 | 9 | - package-ecosystem: "github-actions" 10 | directory: "/" 11 | schedule: 12 | interval: "daily" 13 | 14 | -------------------------------------------------------------------------------- /.github/workflows/ci.yml: -------------------------------------------------------------------------------- 1 | name: CI 2 | 3 | on: 4 | push: 5 | branches: 6 | - main 7 | pull_request: 8 | 9 | jobs: 10 | build: 11 | name: Verify 12 | uses: maveniverse/parent/.github/workflows/ci.yml@release-49 13 | with: 14 | maven-test: './mvnw -f demo install -e -B -V' 15 | -------------------------------------------------------------------------------- /extensions/mmr/README.md: -------------------------------------------------------------------------------- 1 | # MIMA Maven Model Reader (MMR) 2 | 3 | MIMA extension to load Maven models (raw or effective) with resolving them. This extension does NOT build 4 | Maven projects, nor produces Model "as a project being built"! For that use Maven. 5 | 6 | Use this extension to load effective POM/Models of _deployed_ (resolvable) artifacts. 7 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .classpath 2 | .project 3 | .settings/ 4 | target/ 5 | *.ser 6 | *.ec 7 | *.ipr 8 | *.iml 9 | *.iws 10 | .idea/ 11 | .DS_Store 12 | build.rc 13 | pom.xml.tag 14 | pom.xml.releaseBackup 15 | pom.xml.versionsBackup 16 | pom.xml.next 17 | release.properties 18 | dependency-reduced-pom.xml 19 | buildNumber.properties 20 | .mvn/timing.properties 21 | 22 | -------------------------------------------------------------------------------- /extensions/mhc4/README.md: -------------------------------------------------------------------------------- 1 | # MIMA Maven (configured) HttpClient 4.x 2 | 3 | MIMA factory of Maven configured Apache HttpClient 4.x. It creates an ASF HttpClient 4.x instance configured "as Maven does", so all of Maven configuration/auth/proxy is applied to it. 4 | 5 | As Maven Core does not exports any of Apache HttpClient 4.x, it is user duty to make sure all needed is present on classpath. 6 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/model/invoker.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023-2024 Maveniverse Org. 3 | # All rights reserved. This program and the accompanying materials 4 | # are made available under the terms of the Eclipse Public License v2.0 5 | # which accompanies this distribution, and is available at 6 | # https://www.eclipse.org/legal/epl-v20.html 7 | # 8 | 9 | # invoker.mavenOpts = -Dsisu.debug 10 | invoker.debug = true -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/simple/invoker.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023-2024 Maveniverse Org. 3 | # All rights reserved. This program and the accompanying materials 4 | # are made available under the terms of the Eclipse Public License v2.0 5 | # which accompanies this distribution, and is available at 6 | # https://www.eclipse.org/legal/epl-v20.html 7 | # 8 | 9 | # invoker.mavenOpts = -Dsisu.debug 10 | invoker.debug = true -------------------------------------------------------------------------------- /runtime/standalone-shared/src/main/filtered-resources/eu/maveniverse/maven/mima/runtime/shared/internal/version.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023-2024 Maveniverse Org. 3 | # All rights reserved. This program and the accompanying materials 4 | # are made available under the terms of the Eclipse Public License v2.0 5 | # which accompanies this distribution, and is available at 6 | # https://www.eclipse.org/legal/epl-v20.html 7 | # 8 | 9 | version=${version} 10 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/simple-offline/invoker.properties: -------------------------------------------------------------------------------- 1 | # 2 | # Copyright (c) 2023-2024 Maveniverse Org. 3 | # All rights reserved. This program and the accompanying materials 4 | # are made available under the terms of the Eclipse Public License v2.0 5 | # which accompanies this distribution, and is available at 6 | # https://www.eclipse.org/legal/epl-v20.html 7 | # 8 | 9 | invoker.buildResult=failure 10 | # invoker.mavenOpts = -Dsisu.debug 11 | invoker.debug = true -------------------------------------------------------------------------------- /extensions/mmr/src/main/java/eu/maveniverse/maven/mima/extensions/mmr/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | /** 9 | * MMR extension for MIMA. 10 | */ 11 | package eu.maveniverse.maven.mima.extensions.mmr; 12 | -------------------------------------------------------------------------------- /extensions/mhc4/src/main/java/eu/maveniverse/maven/mima/extensions/mhc4/package-info.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | /** 9 | * MHC4 extension for MIMA. 10 | */ 11 | package eu.maveniverse.maven.mima.extensions.mhc4; 12 | -------------------------------------------------------------------------------- /demo/library-standalone-sisu/src/test/resources/encrypted/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | my-server 7 | username 8 | 9 | {BnJray6RajsHJ1EO0G6owUQBV3DNG/bWKiyipdTKeyA=} 10 | 11 | 12 | -------------------------------------------------------------------------------- /demo/library-standalone-static/src/test/resources/encrypted/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 4 | 5 | 6 | my-server 7 | username 8 | 9 | {BnJray6RajsHJ1EO0G6owUQBV3DNG/bWKiyipdTKeyA=} 10 | 11 | 12 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/simple/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | File buildLog = new File( basedir, 'build.log' ) 9 | assert buildLog.exists() 10 | assert buildLog.text.contains( "[DEBUG] Runtimes.getRuntime: MavenRuntime" ) 11 | assert buildLog.text.contains( "[INFO] Classpath of junit:junit:4.13.1 artifact is:" ) 12 | -------------------------------------------------------------------------------- /runtime/standalone-sisu-uber/src/main/java/eu/maveniverse/maven/mima/runtime/standalonesisu/uber/Dummy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonesisu.uber; 9 | 10 | /** 11 | * This class is ONLY here to make this module allowed by Central Staging Ruleset (present of sources and javadoc is must). 12 | */ 13 | public final class Dummy { 14 | private Dummy() {} 15 | } 16 | -------------------------------------------------------------------------------- /runtime/standalone-static-uber/src/main/java/eu/maveniverse/maven/mima/runtime/standalonestatic/uber/Dummy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonestatic.uber; 9 | 10 | /** 11 | * This class is ONLY here to make this module allowed by Central Staging Ruleset (present of sources and javadoc is must). 12 | */ 13 | public final class Dummy { 14 | private Dummy() {} 15 | } 16 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/model/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | File buildLog = new File( basedir, 'build.log' ) 9 | assert buildLog.exists() 10 | if (buildLog.text.contains("Unsupported Maven version")) { 11 | return // ignore the rest 12 | } 13 | assert buildLog.text.contains( "[DEBUG] Runtimes.getRuntime: MavenRuntime" ) 14 | assert buildLog.text.contains( "[INFO] Model of junit:junit:4.13.1 artifact is:" ) 15 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/simple-offline/verify.groovy: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | File buildLog = new File( basedir, 'build.log' ) 9 | assert buildLog.exists() 10 | assert buildLog.text.contains( "[DEBUG] Runtimes.getRuntime: MavenRuntime" ) 11 | assert buildLog.text.contains( "junit:junit:jar:4.13.2" ) // minimal: error messages were improved/changed in Maven 3.9.x 12 | assert buildLog.text.contains( "in offline mode" ) 13 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/MavenUserHome.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context; 9 | 10 | import java.nio.file.Path; 11 | 12 | /** 13 | * Interface pointing to Maven User Home and various locations of interests within it. 14 | * 15 | * @since 2.4.0 16 | */ 17 | public interface MavenUserHome { 18 | Path basedir(); 19 | 20 | Path settingsXml(); 21 | 22 | Path settingsSecurityXml(); 23 | 24 | Path toolchainsXml(); 25 | 26 | Path localRepository(); 27 | 28 | /** 29 | * Derives new maven user home from itself with overrides applied. 30 | * 31 | * @since 2.4.4 32 | */ 33 | MavenUserHome derive(ContextOverrides contextOverrides); 34 | } 35 | -------------------------------------------------------------------------------- /runtime/standalone-sisu-uber/src/assemblies/uber-source.xml: -------------------------------------------------------------------------------- 1 | 10 | 13 | sources 14 | 15 | jar 16 | 17 | 18 | 19 | 20 | ${project.build.directory}/sources 21 | / 22 | true 23 | 24 | 25 | -------------------------------------------------------------------------------- /runtime/standalone-static-uber/src/assemblies/uber-source.xml: -------------------------------------------------------------------------------- 1 | 10 | 13 | sources 14 | 15 | jar 16 | 17 | 18 | 19 | 20 | ${project.build.directory}/sources 21 | / 22 | true 23 | 24 | 25 | -------------------------------------------------------------------------------- /runtime/standalone-sisu/src/main/java/eu/maveniverse/maven/mima/runtime/standalonesisu/internal/Bootstrap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonesisu.internal; 9 | 10 | import eu.maveniverse.maven.mima.context.Runtimes; 11 | import eu.maveniverse.maven.mima.runtime.standalonesisu.StandaloneSisuRuntime; 12 | import javax.inject.Inject; 13 | import javax.inject.Named; 14 | import org.eclipse.sisu.EagerSingleton; 15 | import org.eclipse.sisu.Nullable; 16 | 17 | @Named 18 | @EagerSingleton 19 | public class Bootstrap { 20 | @Inject 21 | public Bootstrap(@Nullable StandaloneSisuRuntime standaloneSisuRuntime) { 22 | if (standaloneSisuRuntime != null) { 23 | Runtimes.INSTANCE.registerRuntime(standaloneSisuRuntime); 24 | } 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/MavenSystemHome.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context; 9 | 10 | import java.nio.file.Path; 11 | 12 | /** 13 | * Interface pointing to Maven System Home and various locations of interests within it. 14 | * 15 | * @since 2.4.0 16 | */ 17 | public interface MavenSystemHome { 18 | Path basedir(); 19 | 20 | Path bin(); 21 | 22 | Path boot(); 23 | 24 | Path conf(); 25 | 26 | Path lib(); 27 | 28 | Path libExt(); 29 | 30 | Path settingsXml(); 31 | 32 | Path toolchainsXml(); 33 | 34 | /** 35 | * Derives new maven system home from itself with overrides applied. 36 | * 37 | * @since 2.4.4 38 | */ 39 | MavenSystemHome derive(ContextOverrides contextOverrides); 40 | } 41 | -------------------------------------------------------------------------------- /extensions/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima 16 | mima 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | eu.maveniverse.maven.mima.extensions 21 | extensions 22 | pom 23 | ${project.groupId}:${project.artifactId} 24 | 25 | 26 | mmr 27 | mhc4 28 | 29 | 30 | -------------------------------------------------------------------------------- /runtime/embedded-maven/src/main/java/eu/maveniverse/maven/mima/runtime/maven/internal/Bootstrap.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.maven.internal; 9 | 10 | import eu.maveniverse.maven.mima.context.Runtimes; 11 | import eu.maveniverse.maven.mima.runtime.maven.MavenRuntime; 12 | import javax.inject.Inject; 13 | import javax.inject.Named; 14 | import org.codehaus.plexus.component.annotations.Component; 15 | import org.eclipse.sisu.EagerSingleton; 16 | import org.eclipse.sisu.Nullable; 17 | 18 | @Named 19 | @EagerSingleton 20 | @Component(role = Bootstrap.class, instantiationStrategy = "load-on-start") 21 | public class Bootstrap { 22 | @Inject 23 | public Bootstrap(@Nullable MavenRuntime mavenEngine) { 24 | if (mavenEngine != null && mavenEngine.isReady()) { 25 | Runtimes.INSTANCE.registerRuntime(mavenEngine); 26 | } 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /runtime/standalone-static/src/main/java/eu/maveniverse/maven/mima/runtime/standalonestatic/SettingsBuilderSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonestatic; 9 | 10 | import java.util.function.Supplier; 11 | import org.apache.maven.settings.building.DefaultSettingsBuilder; 12 | import org.apache.maven.settings.building.SettingsBuilder; 13 | import org.apache.maven.settings.io.DefaultSettingsReader; 14 | import org.apache.maven.settings.io.DefaultSettingsWriter; 15 | import org.apache.maven.settings.validation.DefaultSettingsValidator; 16 | 17 | /** 18 | * Override to customize. 19 | */ 20 | public class SettingsBuilderSupplier implements Supplier { 21 | @Override 22 | public SettingsBuilder get() { 23 | return new DefaultSettingsBuilder( 24 | new DefaultSettingsReader(), new DefaultSettingsWriter(), new DefaultSettingsValidator()); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /runtime/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima 16 | mima 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | eu.maveniverse.maven.mima.runtime 21 | runtime 22 | pom 23 | ${project.groupId}:${project.artifactId} 24 | 25 | 26 | embedded-maven 27 | standalone-shared 28 | standalone-sisu 29 | standalone-sisu-uber 30 | standalone-static 31 | standalone-static-uber 32 | 33 | 34 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/Lookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context; 9 | 10 | import java.util.Optional; 11 | 12 | /** 13 | * A simple "lookup" that allows to lookup various components. Lookup shares lifecycle with {@link Context}. 14 | *

15 | * Note: this component offers access to Resolver internals, but it is up to caller to know really how to use 16 | * this feature (for example due compatibility reasons). Ideally, you do not want to use this, or use it only 17 | * in some "advanced scenarios". 18 | * 19 | * @since 2.4.10 20 | */ 21 | public interface Lookup { 22 | /** 23 | * Performs lookup for component with passed in type, and returns it as optional, never {@code null}. 24 | */ 25 | Optional lookup(Class type); 26 | 27 | /** 28 | * Performs lookup for component with passed in type and name, and returns it as optional, never {@code null}. 29 | */ 30 | Optional lookup(Class type, String name); 31 | } 32 | -------------------------------------------------------------------------------- /demo/README.md: -------------------------------------------------------------------------------- 1 | # MIMA Demo 2 | 3 | ... currently also misused as some sort of IT, run as next step after building MIMA. 4 | 5 | ## What is this about? 6 | 7 | The MIMA Demo showcases its usage outside and inside of Maven. 8 | 9 | It consists of 4 modules: 10 | 11 | * `library` - the reusable "library" that uses MIMA to perform some Resolver task. In this example it 12 | resolves transitive dependencies of an artifact and simply returns a String containing 13 | OS correct classpath for given artifact. 14 | * `library-standalone-sisu` - mimics an "application" that reuses "library" in a "standalone" scenario 15 | and uses Eclipse Sisu DI (hence, "standalone-sisu-uber" runtime is used). It merely invokes the 16 | library and ensures "it works". 17 | * `library-standalone-static` - mimics an "application" that reuses "library" in a "standalone" scenario 18 | and does not uses Eclipse Sisu DI (hence, "standalone-static-uber" runtime is used). It merely invokes the 19 | library and ensures "it works". 20 | * `library-maven-plugin` - a Maven Plugin that reuses "library" within a Mojo running in Maven. To prove 21 | it works, it has Maven Plugin IT implemented using maven-invoker-plugin, the usual way to 22 | implement Maven Plugin ITs. 23 | 24 | Invoking Maven from `demo/` will run all these modules, and in case of success, the build will 25 | finish successfully. 26 | -------------------------------------------------------------------------------- /runtime/embedded-maven/src/main/java/eu/maveniverse/maven/mima/runtime/maven/internal/PlexusLookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.maven.internal; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.Lookup; 13 | import java.util.Optional; 14 | import org.codehaus.plexus.PlexusContainer; 15 | import org.codehaus.plexus.component.repository.exception.ComponentLookupException; 16 | 17 | public final class PlexusLookup implements Lookup { 18 | private final PlexusContainer plexusContainer; 19 | 20 | public PlexusLookup(PlexusContainer plexusContainer) { 21 | this.plexusContainer = requireNonNull(plexusContainer); 22 | } 23 | 24 | @Override 25 | public Optional lookup(Class type) { 26 | try { 27 | return Optional.of(plexusContainer.lookup(type)); 28 | } catch (ComponentLookupException e) { 29 | return Optional.empty(); 30 | } 31 | } 32 | 33 | @Override 34 | public Optional lookup(Class type, String name) { 35 | try { 36 | return Optional.of(plexusContainer.lookup(type, name)); 37 | } catch (ComponentLookupException e) { 38 | return Optional.empty(); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/settings.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 13 | 14 | it-repo 15 | 16 | 17 | local.central 18 | @localRepositoryUrl@ 19 | 20 | true 21 | ignore 22 | 23 | 24 | true 25 | ignore 26 | 27 | 28 | 29 | 30 | 31 | local.central 32 | @localRepositoryUrl@ 33 | 34 | true 35 | ignore 36 | 37 | 38 | true 39 | ignore 40 | 41 | 42 | 43 | 44 | 45 | 46 | it-repo 47 | 48 | -------------------------------------------------------------------------------- /runtime/standalone-sisu/src/main/java/eu/maveniverse/maven/mima/runtime/standalonesisu/internal/MavenSecDispatcherProvider.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonesisu.internal; 9 | 10 | import eu.maveniverse.maven.mima.runtime.shared.PreBoot; 11 | import java.util.Map; 12 | import javax.inject.Inject; 13 | import javax.inject.Named; 14 | import javax.inject.Provider; 15 | import javax.inject.Singleton; 16 | import org.sonatype.plexus.components.cipher.PlexusCipher; 17 | import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; 18 | import org.sonatype.plexus.components.sec.dispatcher.PasswordDecryptor; 19 | import org.sonatype.plexus.components.sec.dispatcher.SecDispatcher; 20 | 21 | @Singleton 22 | @Named("maven") 23 | public class MavenSecDispatcherProvider implements Provider { 24 | private final SecDispatcher secDispatcher; 25 | 26 | @Inject 27 | public MavenSecDispatcherProvider(PreBoot preBoot, PlexusCipher plexusCipher, Map pds) { 28 | this.secDispatcher = new DefaultSecDispatcher( 29 | plexusCipher, 30 | pds, 31 | preBoot.getMavenUserHome().settingsSecurityXml().toString()); 32 | } 33 | 34 | @Override 35 | public SecDispatcher get() { 36 | return secDispatcher; 37 | } 38 | } 39 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/main/java/eu/maveniverse/maven/mima/impl/maven/ClasspathMojo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.impl.maven; 9 | 10 | import eu.maveniverse.maven.mima.context.ContextOverrides; 11 | import eu.maveniverse.maven.mima.impl.library.Classpath; 12 | import org.apache.maven.plugin.AbstractMojo; 13 | import org.apache.maven.plugin.MojoExecutionException; 14 | import org.apache.maven.plugins.annotations.Mojo; 15 | import org.apache.maven.plugins.annotations.Parameter; 16 | 17 | @Mojo(name = "classpath") 18 | public class ClasspathMojo extends AbstractMojo { 19 | @Parameter(required = true) 20 | private String artifact; 21 | 22 | @Parameter 23 | private boolean offline; 24 | 25 | @Override 26 | public void execute() throws MojoExecutionException { 27 | try { 28 | Classpath classpath = new Classpath(); 29 | ContextOverrides overrides = 30 | ContextOverrides.create().offline(offline).build(); 31 | 32 | String cp = classpath.classpath(overrides, artifact); 33 | getLog().info(""); 34 | getLog().info("Classpath of " + artifact + " artifact is:"); 35 | getLog().info(cp); 36 | getLog().info(""); 37 | } catch (Exception e) { 38 | throw new MojoExecutionException("Error:", e); 39 | } 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/model/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 14 | 4.0.0 15 | 16 | eu.maveniverse.maven.mima.impl.maven.its 17 | simple 18 | 1.0 19 | pom 20 | 21 | 22 | Simple smoke test. 23 | 24 | 25 | 26 | 27 | 28 | eu.maveniverse.maven.mima.demo 29 | library-maven-plugin 30 | @project.version@ 31 | 32 | 33 | simple 34 | process-resources 35 | 36 | model 37 | 38 | 39 | 40 | junit:junit:4.13.1 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/simple/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 14 | 4.0.0 15 | 16 | eu.maveniverse.maven.mima.impl.maven.its 17 | simple 18 | 1.0 19 | pom 20 | 21 | 22 | Simple smoke test. 23 | 24 | 25 | 26 | 27 | 28 | eu.maveniverse.maven.mima.demo 29 | library-maven-plugin 30 | @project.version@ 31 | 32 | 33 | simple 34 | process-resources 35 | 36 | classpath 37 | 38 | 39 | 40 | junit:junit:4.13.1 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | -------------------------------------------------------------------------------- /runtime/standalone-static/src/main/java/eu/maveniverse/maven/mima/runtime/standalonestatic/SettingsDecrypterSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonestatic; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.MavenUserHome; 13 | import java.util.Collections; 14 | import java.util.function.Supplier; 15 | import org.apache.maven.settings.crypto.DefaultSettingsDecrypter; 16 | import org.apache.maven.settings.crypto.SettingsDecrypter; 17 | import org.sonatype.plexus.components.cipher.DefaultPlexusCipher; 18 | import org.sonatype.plexus.components.sec.dispatcher.DefaultSecDispatcher; 19 | 20 | /** 21 | * Override to customize. 22 | */ 23 | public class SettingsDecrypterSupplier implements Supplier { 24 | private final MavenUserHome mavenUserHome; 25 | 26 | public SettingsDecrypterSupplier(MavenUserHome mavenUserHome) { 27 | this.mavenUserHome = requireNonNull(mavenUserHome); 28 | } 29 | 30 | @Override 31 | public SettingsDecrypter get() { 32 | DefaultPlexusCipher plexusCipher = new DefaultPlexusCipher(); 33 | DefaultSecDispatcher secDispatcher = new DefaultSecDispatcher( 34 | plexusCipher, 35 | Collections.emptyMap(), 36 | mavenUserHome.settingsSecurityXml().toString()); 37 | return new DefaultSettingsDecrypter(secDispatcher); 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /context/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima 16 | mima 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | context 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | eu.maveniverse.maven.mima.context 25 | 26 | 27 | 28 | 29 | org.apache.maven.resolver 30 | maven-resolver-api 31 | 32 | 33 | org.apache.maven.resolver 34 | maven-resolver-util 35 | 36 | 37 | 38 | org.junit.jupiter 39 | junit-jupiter-api 40 | test 41 | 42 | 43 | org.mockito 44 | mockito-core 45 | test 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/it/simple-offline/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 14 | 4.0.0 15 | 16 | eu.maveniverse.maven.mima.impl.maven.its 17 | simple 18 | 1.0 19 | pom 20 | 21 | 22 | Simple smoke test. 23 | 24 | 25 | 26 | 27 | 28 | eu.maveniverse.maven.mima.demo 29 | library-maven-plugin 30 | @project.version@ 31 | 32 | 33 | simple 34 | process-resources 35 | 36 | classpath 37 | 38 | 39 | true 40 | 41 | junit:junit:4.13.2 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/internal/IteratingLookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context.internal; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.Lookup; 13 | import java.util.*; 14 | 15 | /** 16 | * A {@link Lookup} implementation that is able to iterate through several lookups, applying "first deliver wins" 17 | * strategy. 18 | * 19 | * @since 2.4.10 20 | */ 21 | public final class IteratingLookup implements Lookup { 22 | private final Collection lookups; 23 | 24 | public IteratingLookup(Lookup... lookups) { 25 | this(Arrays.asList(lookups)); 26 | } 27 | 28 | public IteratingLookup(Collection lookups) { 29 | this.lookups = requireNonNull(lookups); 30 | } 31 | 32 | @Override 33 | public Optional lookup(Class type) { 34 | for (Lookup lookup : lookups) { 35 | Optional result = lookup.lookup(type); 36 | if (result.isPresent()) { 37 | return result; 38 | } 39 | } 40 | return Optional.empty(); 41 | } 42 | 43 | @Override 44 | public Optional lookup(Class type, String name) { 45 | for (Lookup lookup : lookups) { 46 | Optional result = lookup.lookup(type, name); 47 | if (result.isPresent()) { 48 | return result; 49 | } 50 | } 51 | return Optional.empty(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/src/main/java/eu/maveniverse/maven/mima/impl/maven/ModelMojo.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.impl.maven; 9 | 10 | import eu.maveniverse.maven.mima.context.ContextOverrides; 11 | import eu.maveniverse.maven.mima.impl.library.Classpath; 12 | import org.apache.maven.plugin.AbstractMojo; 13 | import org.apache.maven.plugin.MojoExecutionException; 14 | import org.apache.maven.plugins.annotations.Component; 15 | import org.apache.maven.plugins.annotations.Mojo; 16 | import org.apache.maven.plugins.annotations.Parameter; 17 | import org.apache.maven.rtinfo.RuntimeInformation; 18 | 19 | @Mojo(name = "model") 20 | public class ModelMojo extends AbstractMojo { 21 | @Parameter(required = true) 22 | private String artifact; 23 | 24 | @Parameter 25 | private boolean offline; 26 | 27 | @Component 28 | private RuntimeInformation runtimeInformation; 29 | 30 | @Override 31 | public void execute() throws MojoExecutionException { 32 | try { 33 | Classpath classpath = new Classpath(); 34 | ContextOverrides overrides = 35 | ContextOverrides.create().offline(offline).build(); 36 | 37 | String md = classpath.model(overrides, artifact); 38 | getLog().info(""); 39 | getLog().info("Model of " + artifact + " artifact is:"); 40 | getLog().info(md); 41 | getLog().info(""); 42 | } catch (Exception e) { 43 | throw new MojoExecutionException("Error:", e); 44 | } 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /runtime/standalone-static/src/main/java/eu/maveniverse/maven/mima/runtime/standalonestatic/ProfileSelectorSupplier.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonestatic; 9 | 10 | import java.util.function.Supplier; 11 | import org.apache.maven.model.path.DefaultPathTranslator; 12 | import org.apache.maven.model.path.ProfileActivationFilePathInterpolator; 13 | import org.apache.maven.model.profile.DefaultProfileSelector; 14 | import org.apache.maven.model.profile.ProfileSelector; 15 | import org.apache.maven.model.profile.activation.FileProfileActivator; 16 | import org.apache.maven.model.profile.activation.JdkVersionProfileActivator; 17 | import org.apache.maven.model.profile.activation.OperatingSystemProfileActivator; 18 | import org.apache.maven.model.profile.activation.PropertyProfileActivator; 19 | 20 | /** 21 | * Override to customize. 22 | */ 23 | public class ProfileSelectorSupplier implements Supplier { 24 | @Override 25 | public ProfileSelector get() { 26 | return new DefaultProfileSelector() 27 | .addProfileActivator(new JdkVersionProfileActivator()) 28 | .addProfileActivator(new PropertyProfileActivator()) 29 | .addProfileActivator(new OperatingSystemProfileActivator()) 30 | .addProfileActivator(new FileProfileActivator() 31 | .setProfileActivationFilePathInterpolator(new ProfileActivationFilePathInterpolator() 32 | .setPathTranslator(new DefaultPathTranslator()))); 33 | } 34 | } 35 | -------------------------------------------------------------------------------- /runtime/standalone-sisu/src/main/java/eu/maveniverse/maven/mima/runtime/standalonesisu/internal/SisuLookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonesisu.internal; 9 | 10 | import com.google.inject.Key; 11 | import com.google.inject.name.Names; 12 | import eu.maveniverse.maven.mima.context.Lookup; 13 | import java.util.Iterator; 14 | import java.util.Optional; 15 | import javax.inject.Named; 16 | import javax.inject.Provider; 17 | import org.eclipse.sisu.BeanEntry; 18 | import org.eclipse.sisu.inject.MutableBeanLocator; 19 | 20 | public class SisuLookup implements Lookup { 21 | private final MutableBeanLocator locator; 22 | 23 | public SisuLookup(MutableBeanLocator locator) { 24 | this.locator = locator; 25 | } 26 | 27 | private Optional lookupInternal(Key key) { 28 | final Iterable> entries = locator.locate(key); 29 | final Iterator> iterator = entries.iterator(); 30 | final Provider provider = iterator.hasNext() ? iterator.next().getProvider() : null; 31 | if (provider == null) { 32 | return Optional.empty(); 33 | } 34 | return Optional.of(provider.get()); 35 | } 36 | 37 | @Override 38 | public Optional lookup(Class type) { 39 | return lookupInternal(Key.get(type, Named.class)); 40 | } 41 | 42 | @Override 43 | public Optional lookup(Class type, String name) { 44 | return lookupInternal(Key.get(type, Names.named(name))); 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /demo/library-standalone-sisu/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.demo 16 | demo 17 | 1.0.0-SNAPSHOT 18 | 19 | 20 | library-standalone-sisu 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | 25 | eu.maveniverse.maven.mima.demo 26 | library 27 | 28 | 29 | 30 | eu.maveniverse.maven.mima.runtime 31 | standalone-sisu-uber 32 | runtime 33 | 34 | 35 | 36 | org.slf4j 37 | slf4j-api 38 | runtime 39 | 40 | 41 | org.slf4j 42 | jcl-over-slf4j 43 | runtime 44 | 45 | 46 | org.slf4j 47 | slf4j-simple 48 | runtime 49 | 50 | 51 | 52 | org.junit.jupiter 53 | junit-jupiter-api 54 | test 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /demo/library-standalone-static/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.demo 16 | demo 17 | 1.0.0-SNAPSHOT 18 | 19 | 20 | library-standalone-static 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | 25 | eu.maveniverse.maven.mima.demo 26 | library 27 | 28 | 29 | 30 | eu.maveniverse.maven.mima.runtime 31 | standalone-static-uber 32 | runtime 33 | 34 | 35 | 36 | org.slf4j 37 | slf4j-api 38 | runtime 39 | 40 | 41 | org.slf4j 42 | jcl-over-slf4j 43 | runtime 44 | 45 | 46 | org.slf4j 47 | slf4j-simple 48 | runtime 49 | 50 | 51 | 52 | org.junit.jupiter 53 | junit-jupiter-api 54 | test 55 | 56 | 57 | 58 | -------------------------------------------------------------------------------- /runtime/standalone-shared/src/main/java/eu/maveniverse/maven/mima/runtime/shared/PreBoot.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.shared; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.ContextOverrides; 13 | import eu.maveniverse.maven.mima.context.MavenUserHome; 14 | import eu.maveniverse.maven.mima.context.internal.MavenSystemHomeImpl; 15 | import eu.maveniverse.maven.mima.context.internal.MavenUserHomeImpl; 16 | import java.nio.file.Path; 17 | 18 | /** 19 | * Pre-boot derived and pre-processed state of MIMA, with not all configuration applied (!), as settings.xml 20 | * was not yet processed (and it may alter {@link MavenUserHome#localRepository()}). 21 | *

22 | * For internal use only in runtimes. 23 | */ 24 | public final class PreBoot { 25 | private final ContextOverrides overrides; 26 | 27 | private final MavenUserHomeImpl mavenUserHome; 28 | 29 | private final MavenSystemHomeImpl mavenSystemHome; 30 | 31 | private final Path baseDir; 32 | 33 | public PreBoot( 34 | ContextOverrides overrides, 35 | MavenUserHomeImpl mavenUserHome, 36 | MavenSystemHomeImpl mavenSystemHome, 37 | Path baseDir) { 38 | this.overrides = requireNonNull(overrides); 39 | this.mavenUserHome = requireNonNull(mavenUserHome); 40 | this.mavenSystemHome = mavenSystemHome; // nullable 41 | this.baseDir = requireNonNull(baseDir); 42 | } 43 | 44 | public ContextOverrides getOverrides() { 45 | return overrides; 46 | } 47 | 48 | public MavenUserHomeImpl getMavenUserHome() { 49 | return mavenUserHome; 50 | } 51 | 52 | public MavenSystemHomeImpl getMavenSystemHome() { 53 | return mavenSystemHome; 54 | } 55 | 56 | public Path getBaseDir() { 57 | return baseDir; 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /runtime/embedded-maven/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.runtime 16 | runtime 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | embedded-maven 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | eu.maveniverse.maven.mima.runtime.maven 25 | 26 | 27 | 28 | 29 | eu.maveniverse.maven.mima 30 | context 31 | provided 32 | 33 | 34 | org.apache.maven.resolver 35 | maven-resolver-api 36 | provided 37 | 38 | 39 | org.apache.maven.resolver 40 | maven-resolver-spi 41 | provided 42 | 43 | 44 | org.apache.maven.resolver 45 | maven-resolver-util 46 | provided 47 | 48 | 49 | org.apache.maven 50 | maven-core 51 | provided 52 | 53 | 54 | org.codehaus.plexus 55 | plexus-component-annotations 56 | 2.2.0 57 | provided 58 | 59 | 60 | 61 | -------------------------------------------------------------------------------- /runtime/standalone-static/src/main/java/eu/maveniverse/maven/mima/runtime/standalonestatic/StaticLookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonestatic; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.Lookup; 13 | import eu.maveniverse.maven.mima.runtime.shared.PreBoot; 14 | import java.util.Optional; 15 | import org.apache.maven.model.profile.ProfileSelector; 16 | import org.apache.maven.settings.building.SettingsBuilder; 17 | import org.apache.maven.settings.crypto.SettingsDecrypter; 18 | 19 | public class StaticLookup implements Lookup { 20 | private final ProfileSelector profileSelector; 21 | private final SettingsBuilder settingsBuilder; 22 | private final SettingsDecrypter settingsDecrypter; 23 | 24 | public StaticLookup(PreBoot preBoot) { 25 | requireNonNull(preBoot); 26 | this.profileSelector = new ProfileSelectorSupplier().get(); 27 | this.settingsBuilder = new SettingsBuilderSupplier().get(); 28 | this.settingsDecrypter = new SettingsDecrypterSupplier(preBoot.getMavenUserHome()).get(); 29 | } 30 | 31 | @SuppressWarnings("unchecked") 32 | @Override 33 | public Optional lookup(Class type) { 34 | if (type.isAssignableFrom(ProfileSelector.class)) { 35 | return (Optional) Optional.of(profileSelector); 36 | } else if (type.isAssignableFrom(SettingsBuilder.class)) { 37 | return (Optional) Optional.of(settingsBuilder); 38 | } else if (type.isAssignableFrom(SettingsDecrypter.class)) { 39 | return (Optional) Optional.of(settingsDecrypter); 40 | } else { 41 | return Optional.empty(); 42 | } 43 | } 44 | 45 | @Override 46 | public Optional lookup(Class type, String name) { 47 | if ("".equals(name) || "default".equals(name)) { 48 | return lookup(type); 49 | } 50 | return Optional.empty(); 51 | } 52 | } 53 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/HTTPProxy.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import java.util.Collections; 13 | import java.util.Map; 14 | 15 | /** 16 | * HTTP Proxy configuration, that resolver uses. 17 | * 18 | * @since 2.4.0 19 | */ 20 | public final class HTTPProxy { 21 | private final String protocol; 22 | 23 | private final String host; 24 | 25 | private final int port; 26 | 27 | private final String nonProxyHosts; 28 | 29 | private final Map data; 30 | 31 | public HTTPProxy(String protocol, String host, int port, String nonProxyHosts, Map data) { 32 | this.protocol = requireNonNull(protocol); 33 | this.host = requireNonNull(host); 34 | this.port = port; 35 | this.nonProxyHosts = nonProxyHosts != null ? nonProxyHosts : ""; 36 | this.data = data != null ? Collections.unmodifiableMap(data) : Collections.emptyMap(); 37 | } 38 | 39 | /** 40 | * The protocol to use with HTTP Proxy, never {@code null}. 41 | */ 42 | public String getProtocol() { 43 | return protocol; 44 | } 45 | 46 | /** 47 | * The HTTP Proxy hostname, never {@code null}. 48 | */ 49 | public String getHost() { 50 | return host; 51 | } 52 | 53 | /** 54 | * The HTTP Proxy port. 55 | */ 56 | public int getPort() { 57 | return port; 58 | } 59 | 60 | /** 61 | * String of comma or pipe delimited list of non-proxy hosts, never {@code null}. 62 | * 63 | * @see Maven Settings Reference - Proxies 64 | */ 65 | public String getNonProxyHosts() { 66 | return nonProxyHosts; 67 | } 68 | 69 | /** 70 | * Extra "data", like auth, never {@code null}. 71 | */ 72 | public Map getData() { 73 | return data; 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /runtime/standalone-static/src/main/java/eu/maveniverse/maven/mima/runtime/standalonestatic/CompatLookup.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonestatic; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.Lookup; 13 | import eu.maveniverse.maven.mima.runtime.shared.PreBoot; 14 | import java.util.Optional; 15 | import org.apache.maven.model.interpolation.DefaultModelVersionProcessor; 16 | import org.apache.maven.model.interpolation.StringVisitorModelInterpolator; 17 | import org.apache.maven.model.path.DefaultPathTranslator; 18 | import org.apache.maven.model.path.DefaultUrlNormalizer; 19 | 20 | /** 21 | * Certain classes that are not exposed via Maven supplier. 22 | */ 23 | public class CompatLookup implements Lookup { 24 | private final StringVisitorModelInterpolator stringVisitorModelInterpolator; 25 | 26 | public CompatLookup(PreBoot preBoot) { 27 | requireNonNull(preBoot); 28 | // StringVisitorModelInterpolator mvn3 vs mvn4 = field vs ctor injection, do DI should protect us from it 29 | this.stringVisitorModelInterpolator = new StringVisitorModelInterpolator(); 30 | this.stringVisitorModelInterpolator 31 | .setPathTranslator(new DefaultPathTranslator()) 32 | .setUrlNormalizer(new DefaultUrlNormalizer()) 33 | .setVersionPropertiesProcessor(new DefaultModelVersionProcessor()); 34 | } 35 | 36 | @SuppressWarnings("unchecked") 37 | @Override 38 | public Optional lookup(Class type) { 39 | if (type.isAssignableFrom(StringVisitorModelInterpolator.class)) { 40 | return (Optional) Optional.of(stringVisitorModelInterpolator); 41 | } else { 42 | return Optional.empty(); 43 | } 44 | } 45 | 46 | @Override 47 | public Optional lookup(Class type, String name) { 48 | if ("".equals(name) || "default".equals(name)) { 49 | return lookup(type); 50 | } 51 | return Optional.empty(); 52 | } 53 | } 54 | -------------------------------------------------------------------------------- /runtime/standalone-sisu/src/main/java/eu/maveniverse/maven/mima/runtime/standalonesisu/internal/SisuBooter.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonesisu.internal; 9 | 10 | import com.google.inject.AbstractModule; 11 | import com.google.inject.Guice; 12 | import com.google.inject.Module; 13 | import eu.maveniverse.maven.mima.runtime.shared.PreBoot; 14 | import java.io.Closeable; 15 | import javax.inject.Inject; 16 | import javax.inject.Named; 17 | import javax.inject.Singleton; 18 | import org.apache.maven.model.profile.ProfileSelector; 19 | import org.apache.maven.settings.building.SettingsBuilder; 20 | import org.apache.maven.settings.crypto.SettingsDecrypter; 21 | import org.eclipse.aether.RepositorySystem; 22 | import org.eclipse.sisu.bean.LifecycleManager; 23 | import org.eclipse.sisu.inject.MutableBeanLocator; 24 | import org.eclipse.sisu.launch.Main; 25 | import org.eclipse.sisu.space.BeanScanning; 26 | 27 | @Singleton 28 | @Named 29 | public class SisuBooter implements Closeable { 30 | @Inject 31 | public RepositorySystem repositorySystem; 32 | 33 | @Inject 34 | public SettingsBuilder settingsBuilder; 35 | 36 | @Inject 37 | public SettingsDecrypter settingsDecrypter; 38 | 39 | @Inject 40 | public ProfileSelector profileSelector; 41 | 42 | @Inject 43 | public LifecycleManager lifecycleManager; 44 | 45 | @Inject 46 | public MutableBeanLocator locator; 47 | 48 | @Override 49 | public void close() { 50 | try { 51 | repositorySystem.shutdown(); 52 | } finally { 53 | lifecycleManager.unmanage(); 54 | locator.clear(); 55 | } 56 | } 57 | 58 | public static SisuBooter newSisuBooter(PreBoot preBoot) { 59 | final Module app = Main.wire(BeanScanning.CACHE, new AbstractModule() { 60 | @Override 61 | protected void configure() { 62 | bind(PreBoot.class).toInstance(preBoot); 63 | } 64 | }); 65 | return Guice.createInjector(app).getInstance(SisuBooter.class); 66 | } 67 | } 68 | -------------------------------------------------------------------------------- /runtime/standalone-shared/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.runtime 16 | runtime 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | standalone-shared 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | eu.maveniverse.maven.mima.runtime.shared 25 | 26 | 27 | 28 | 29 | eu.maveniverse.maven.mima 30 | context 31 | provided 32 | 33 | 34 | org.slf4j 35 | slf4j-api 36 | provided 37 | 38 | 39 | org.apache.maven.resolver 40 | maven-resolver-api 41 | provided 42 | 43 | 44 | org.apache.maven.resolver 45 | maven-resolver-util 46 | provided 47 | 48 | 49 | org.apache.maven 50 | maven-resolver-provider 51 | provided 52 | 53 | 54 | org.apache.maven 55 | maven-model-builder 56 | provided 57 | 58 | 59 | org.apache.maven 60 | maven-settings-builder 61 | provided 62 | 63 | 64 | 65 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/Runtime.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context; 9 | 10 | /** 11 | * Runtime is a factory for {@link Context} instances. 12 | */ 13 | public interface Runtime { 14 | /** 15 | * String representation returned for versions, when discovery was unsuccessful. 16 | * 17 | * @since 2.4.38 18 | */ 19 | String UNKNOWN_VERSION = "(unknown)"; 20 | 21 | /** 22 | * The runtime name (mostly for keying purposes), never {@code null}. 23 | */ 24 | String name(); 25 | 26 | /** 27 | * The runtime version, never {@code null}. 28 | */ 29 | String version(); 30 | 31 | /** 32 | * The priority of runtime instance. Priorities use natural integer ordering. 33 | */ 34 | int priority(); 35 | 36 | /** 37 | * Returns a string representing Maven version this runtime uses, never {@code null}. This mostly stands for 38 | * "maven models" version, except when MIMA runs inside of Maven, when it carries the "actual Maven version". 39 | */ 40 | String mavenVersion(); 41 | 42 | /** 43 | * Returns a string representing Resolver version this runtime uses, never {@code null}. In case of embedded 44 | * Maven, discovery of resolver is not possible due Maven classloader encapsulation (then resolver version 45 | * can be derived from Maven version). 46 | * 47 | * @since 2.4.38 48 | * @return discovered resolver version or {@link #UNKNOWN_VERSION} 49 | */ 50 | String resolverVersion(); 51 | 52 | /** 53 | * Returns {@code true} if this runtime creates managed repository system, that is opposite when MIMA runs 54 | * in Maven (or any other environment providing resolver), where it does not manage it, as hosting Maven or app 55 | * does. In general, you should always treat "root context" as explained in {@link Context} and your code will be 56 | * portable. 57 | */ 58 | boolean managedRepositorySystem(); 59 | 60 | /** 61 | * Creates a {@link Context} instance using passed in {@link ContextOverrides}, never returns {@code null}. 62 | */ 63 | Context create(ContextOverrides overrides); 64 | } 65 | -------------------------------------------------------------------------------- /context/src/test/java/eu/maveniverse/maven/mima/context/ContextOverridesTest.java: -------------------------------------------------------------------------------- 1 | package eu.maveniverse.maven.mima.context; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNotEquals; 5 | 6 | import java.nio.file.Paths; 7 | import java.util.HashMap; 8 | import org.junit.jupiter.api.Test; 9 | 10 | class ContextOverridesTest { 11 | @Test 12 | void contextBuilderContext() { 13 | ContextOverrides co1 = ContextOverrides.create().build(); 14 | ContextOverrides co2 = co1.toBuilder().build(); 15 | assertEquals(co1, co2); 16 | } 17 | 18 | @Test 19 | void contextBuilderLocalRepositoryOverrideNullContext() { 20 | ContextOverrides co1 = ContextOverrides.create().build(); 21 | ContextOverrides co2 = co1.toBuilder().withLocalRepositoryOverride(null).build(); 22 | assertEquals(co1, co2); 23 | } 24 | 25 | @Test 26 | void contextBuilderLocalRepositoryOverrideNonNullContext() { 27 | ContextOverrides co1 = ContextOverrides.create().build(); 28 | ContextOverrides co2 = 29 | co1.toBuilder().withLocalRepositoryOverride(Paths.get("foo")).build(); 30 | assertNotEquals(co1, co2); 31 | 32 | ContextOverrides co3 = co2.toBuilder().withLocalRepositoryOverride(null).build(); 33 | assertEquals(co1, co3); 34 | } 35 | 36 | @Test 37 | void userProperties() { 38 | HashMap userProperties = new HashMap<>(); 39 | userProperties.put("foo", "bar"); 40 | 41 | ContextOverrides co1 = 42 | ContextOverrides.create().userProperties(userProperties).build(); 43 | ContextOverrides co2 = co1.toBuilder().build(); 44 | ContextOverrides co3 = co2.toBuilder().userProperties(null).build(); 45 | userProperties.put("foo", "baz"); 46 | ContextOverrides co4 = co3.toBuilder().userProperties(userProperties).build(); 47 | userProperties.put("foo", "bar"); 48 | ContextOverrides co5 = co4.toBuilder().userProperties(userProperties).build(); 49 | 50 | assertEquals(co1, co2); 51 | assertEquals(co1.getUserProperties().get("foo"), "bar"); 52 | assertEquals(co2.getUserProperties().get("foo"), "bar"); 53 | assertNotEquals(co1, co3); 54 | assertEquals(co3.getUserProperties().get("foo"), null); 55 | assertNotEquals(co1, co4); 56 | assertEquals(co4.getUserProperties().get("foo"), "baz"); 57 | assertEquals(co1, co5); 58 | assertEquals(co5.getUserProperties().get("foo"), "bar"); 59 | } 60 | } 61 | -------------------------------------------------------------------------------- /extensions/mhc4/src/main/java/eu/maveniverse/maven/mima/extensions/mhc4/MavenHttpClient4Factory.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.extensions.mhc4; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.Context; 13 | import eu.maveniverse.maven.mima.extensions.mhc4.impl.MavenHttpClient4FactoryImpl; 14 | import org.apache.http.impl.client.HttpClientBuilder; 15 | import org.eclipse.aether.ConfigurationProperties; 16 | import org.eclipse.aether.repository.RemoteRepository; 17 | 18 | /** 19 | * Maven HttpClient 4.x factory. Creates Maven env configured {@link HttpClientBuilder} instance. 20 | *

21 | * Configuration not applied, which should be handled by caller/user of this factory: 22 | *

28 | *

29 | * Differences between {@link #createResolutionClient(RemoteRepository)} and {@link #createDeploymentClient(RemoteRepository)} 30 | * are exactly the same as in Maven/Resolver. See corresponding Javadoc. 31 | * 32 | * @see MavenHttpClient4FactoryImpl 33 | */ 34 | public class MavenHttpClient4Factory { 35 | protected final Context context; 36 | protected final MavenHttpClient4FactoryImpl factory; 37 | 38 | /** 39 | * Creates instance using passed in context. 40 | */ 41 | public MavenHttpClient4Factory(Context context) { 42 | this.context = requireNonNull(context); 43 | this.factory = new MavenHttpClient4FactoryImpl(context.repositorySystem()); 44 | } 45 | 46 | /** 47 | * Creates {@link HttpClientBuilder} preconfigured from Maven environment for resolving. 48 | */ 49 | public HttpClientBuilder createResolutionClient(RemoteRepository repository) { 50 | return factory.createResolutionClient(context.repositorySystemSession(), repository); 51 | } 52 | 53 | /** 54 | * Creates {@link HttpClientBuilder} preconfigured from Maven environment for deployment. 55 | */ 56 | public HttpClientBuilder createDeploymentClient(RemoteRepository repository) { 57 | return factory.createDeploymentClient(context.repositorySystemSession(), repository); 58 | } 59 | } 60 | -------------------------------------------------------------------------------- /demo/library/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.demo 16 | demo 17 | 1.0.0-SNAPSHOT 18 | 19 | 20 | library 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | 25 | 26 | org.slf4j 27 | slf4j-api 28 | 29 | 30 | eu.maveniverse.maven.mima 31 | context 32 | 33 | 34 | eu.maveniverse.maven.mima.extensions 35 | mmr 36 | 37 | 38 | org.apache.maven 39 | maven-model 40 | ${version.maven} 41 | provided 42 | 43 | 44 | org.apache.maven.resolver 45 | maven-resolver-api 46 | ${version.resolver} 47 | provided 48 | 49 | 50 | org.apache.maven.resolver 51 | maven-resolver-spi 52 | ${version.resolver} 53 | provided 54 | 55 | 56 | org.apache.maven.resolver 57 | maven-resolver-impl 58 | ${version.resolver} 59 | provided 60 | 61 | 62 | 63 | eu.maveniverse.maven.mima.runtime 64 | embedded-maven 65 | ${version.mima} 66 | runtime 67 | 68 | 69 | 70 | org.junit.jupiter 71 | junit-jupiter-api 72 | test 73 | 74 | 75 | 76 | -------------------------------------------------------------------------------- /context/src/test/java/eu/maveniverse/maven/mima/context/internal/RuntimeSupportTest.java: -------------------------------------------------------------------------------- 1 | package eu.maveniverse.maven.mima.context.internal; 2 | 3 | import eu.maveniverse.maven.mima.context.Context; 4 | import eu.maveniverse.maven.mima.context.ContextOverrides; 5 | import eu.maveniverse.maven.mima.context.Lookup; 6 | import java.nio.file.Paths; 7 | import java.util.List; 8 | import java.util.Optional; 9 | import org.eclipse.aether.DefaultRepositorySystemSession; 10 | import org.eclipse.aether.RepositorySystem; 11 | import org.eclipse.aether.RepositorySystemSession; 12 | import org.eclipse.aether.repository.RemoteRepository; 13 | import org.junit.jupiter.api.Assertions; 14 | import org.junit.jupiter.api.Test; 15 | import org.mockito.Mockito; 16 | 17 | class RuntimeSupportTest { 18 | @Test 19 | void itPropagatesNullMavenSystemHome() { 20 | RuntimeSupport runtimeSupport = new RuntimeSupport("test", "123", 999, "123", "123") { 21 | @Override 22 | public boolean managedRepositorySystem() { 23 | return false; 24 | } 25 | 26 | @Override 27 | public Context create(ContextOverrides overrides) { 28 | return null; 29 | } 30 | 31 | @Override 32 | protected void customizeLocalRepositoryManager(Context context, DefaultRepositorySystemSession session) { 33 | // Intentionally skipped 34 | } 35 | 36 | @Override 37 | protected List customizeRemoteRepositories( 38 | ContextOverrides contextOverrides, List remoteRepositories) { 39 | // Intentionally skipped 40 | return remoteRepositories; 41 | } 42 | }; 43 | 44 | Context context = new Context( 45 | runtimeSupport, 46 | ContextOverrides.create().build(), 47 | Paths.get("/test"), 48 | runtimeSupport.defaultMavenUserHome(), 49 | null, 50 | Mockito.mock(RepositorySystem.class), 51 | Mockito.mock(RepositorySystemSession.class), 52 | null, 53 | new Lookup() { 54 | @Override 55 | public Optional lookup(Class type) { 56 | return Optional.empty(); 57 | } 58 | 59 | @Override 60 | public Optional lookup(Class type, String name) { 61 | return Optional.empty(); 62 | } 63 | }, 64 | null); 65 | 66 | ContextOverrides overrides = 67 | ContextOverrides.create().offline(Boolean.TRUE).build(); 68 | 69 | Assertions.assertDoesNotThrow(() -> runtimeSupport.customizeContext(overrides, context, false)); 70 | } 71 | } 72 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/Runtimes.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import java.util.Collection; 13 | import java.util.Collections; 14 | import java.util.Comparator; 15 | import java.util.ServiceLoader; 16 | import java.util.TreeSet; 17 | 18 | /** 19 | * Registry of known {@link Runtime} instances. It orders them by priority. This class is the "entry point" in MIMA to 20 | * obtain actual {@link Runtime} instance. 21 | */ 22 | public final class Runtimes { 23 | public static final Runtimes INSTANCE = new Runtimes(); 24 | 25 | private final TreeSet runtimes = new TreeSet<>(Comparator.comparing(Runtime::priority)); 26 | 27 | private Runtimes() {} 28 | 29 | /** 30 | * Returns the {@link Runtime} instance with the highest priority out of all registered instances, never 31 | * {@code null}. The method should be used to obtains runtime instance to work with. 32 | */ 33 | public synchronized Runtime getRuntime() { 34 | Runtime result = null; 35 | if (!runtimes.isEmpty()) { 36 | result = runtimes.first(); 37 | } 38 | if (result == null) { 39 | ServiceLoader loader = ServiceLoader.load(Runtime.class); 40 | loader.iterator().forEachRemaining(this::registerRuntime); 41 | if (runtimes.isEmpty()) { 42 | throw new IllegalStateException("No Runtime implementation found on classpath"); 43 | } 44 | result = runtimes.first(); 45 | } 46 | return result; 47 | } 48 | 49 | /** 50 | * Returns an unmodifiable snapshot (copy) collection of all registered {@link Runtime} instances. 51 | */ 52 | public synchronized Collection getRuntimes() { 53 | TreeSet result = new TreeSet<>(Comparator.comparing(Runtime::priority)); 54 | result.addAll(runtimes); 55 | return Collections.unmodifiableSet(result); 56 | } 57 | 58 | /** 59 | * Registers a {@link Runtime} instance. If instance with same {@link Runtime#name()} was already registered, this 60 | * method is no-op (first registration wins). 61 | */ 62 | public synchronized void registerRuntime(Runtime mimaRuntime) { 63 | requireNonNull(mimaRuntime); 64 | if (runtimes.stream().map(Runtime::name).noneMatch(n -> n.equals(mimaRuntime.name()))) { 65 | runtimes.add(mimaRuntime); 66 | } 67 | } 68 | 69 | /** 70 | * Clears all registered instances. 71 | */ 72 | public synchronized void resetRuntimes() { 73 | runtimes.clear(); 74 | } 75 | } 76 | -------------------------------------------------------------------------------- /demo/library-maven-plugin/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.demo 16 | demo 17 | 1.0.0-SNAPSHOT 18 | 19 | 20 | library-maven-plugin 21 | maven-plugin 22 | ${project.groupId}:${project.artifactId} 23 | 24 | 25 | 3.6.3 26 | 27 | 28 | 29 | 30 | eu.maveniverse.maven.mima.demo 31 | library 32 | 33 | 34 | 35 | org.apache.maven 36 | maven-plugin-api 37 | ${version.maven} 38 | provided 39 | 40 | 41 | org.apache.maven 42 | maven-core 43 | ${version.maven} 44 | provided 45 | 46 | 47 | org.apache.maven.plugin-tools 48 | maven-plugin-annotations 49 | 3.15.1 50 | provided 51 | 52 | 53 | 54 | 55 | 56 | 57 | org.apache.maven.plugins 58 | maven-plugin-plugin 59 | 60 | 61 | org.apache.maven.plugins 62 | maven-invoker-plugin 63 | 64 | ${project.build.directory}/it 65 | true 66 | 67 | */pom.xml 68 | 69 | setup 70 | verify 71 | ${project.build.directory}/local-repo 72 | src/it/settings.xml 73 | 74 | package 75 | 76 | 77 | 78 | 79 | integration-test 80 | 81 | install 82 | integration-test 83 | verify 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | -------------------------------------------------------------------------------- /runtime/standalone-static/src/main/java/eu/maveniverse/maven/mima/runtime/standalonestatic/StandaloneStaticRuntime.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonestatic; 9 | 10 | import eu.maveniverse.maven.mima.context.Context; 11 | import eu.maveniverse.maven.mima.context.ContextOverrides; 12 | import eu.maveniverse.maven.mima.context.Lookup; 13 | import eu.maveniverse.maven.mima.context.internal.IteratingLookup; 14 | import eu.maveniverse.maven.mima.runtime.shared.PreBoot; 15 | import eu.maveniverse.maven.mima.runtime.shared.StandaloneRuntimeSupport; 16 | import java.util.NoSuchElementException; 17 | import org.apache.maven.model.profile.ProfileSelector; 18 | import org.apache.maven.settings.building.SettingsBuilder; 19 | import org.apache.maven.settings.crypto.SettingsDecrypter; 20 | import org.eclipse.aether.RepositorySystem; 21 | 22 | public class StandaloneStaticRuntime extends StandaloneRuntimeSupport { 23 | 24 | public StandaloneStaticRuntime() { 25 | this("standalone-static", 40); 26 | } 27 | 28 | public StandaloneStaticRuntime(String name, int priority) { 29 | super(name, priority); 30 | } 31 | 32 | @Override 33 | public boolean managedRepositorySystem() { 34 | return true; 35 | } 36 | 37 | @Override 38 | public Context create(ContextOverrides overrides) { 39 | PreBoot preBoot = preBoot(overrides); 40 | Lookup lookup = new IteratingLookup( 41 | createStaticLookup(preBoot), createRepositorySystemLookup(preBoot), createCompatLookup(preBoot)); 42 | RepositorySystem repositorySystem = lookup.lookup(RepositorySystem.class) 43 | .orElseThrow(() -> new NoSuchElementException("No RepositorySystem present")); 44 | SettingsBuilder settingsBuilder = lookup.lookup(SettingsBuilder.class) 45 | .orElseThrow(() -> new NoSuchElementException("No SettingsBuilder present")); 46 | SettingsDecrypter settingsDecrypter = lookup.lookup(SettingsDecrypter.class) 47 | .orElseThrow(() -> new NoSuchElementException("No SettingsDecrypter present")); 48 | ProfileSelector profileSelector = lookup.lookup(ProfileSelector.class) 49 | .orElseThrow(() -> new NoSuchElementException("No ProfileSelector present")); 50 | return buildContext( 51 | this, 52 | preBoot, 53 | repositorySystem, 54 | settingsBuilder, 55 | settingsDecrypter, 56 | profileSelector, 57 | lookup, 58 | repositorySystem::shutdown); 59 | } 60 | 61 | protected Lookup createStaticLookup(PreBoot preBoot) { 62 | return new StaticLookup(preBoot); 63 | } 64 | 65 | protected Lookup createRepositorySystemLookup(PreBoot preBoot) { 66 | return new MemoizingRepositorySystemSupplierLookup(); 67 | } 68 | 69 | protected Lookup createCompatLookup(PreBoot preBoot) { 70 | return new CompatLookup(preBoot); 71 | } 72 | } 73 | -------------------------------------------------------------------------------- /runtime/standalone-sisu/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.runtime 16 | runtime 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | standalone-sisu 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | eu.maveniverse.maven.mima.runtime.standalonesisu 25 | 26 | 27 | 28 | 29 | eu.maveniverse.maven.mima 30 | context 31 | provided 32 | 33 | 34 | eu.maveniverse.maven.mima.runtime 35 | standalone-shared 36 | 37 | 38 | org.apache.maven.resolver 39 | maven-resolver-api 40 | 41 | 42 | org.apache.maven.resolver 43 | maven-resolver-spi 44 | 45 | 46 | org.apache.maven.resolver 47 | maven-resolver-util 48 | 49 | 50 | org.apache.maven.resolver 51 | maven-resolver-connector-basic 52 | 53 | 54 | org.apache.maven.resolver 55 | maven-resolver-named-locks 56 | 57 | 58 | org.apache.maven.resolver 59 | maven-resolver-impl 60 | 61 | 62 | org.apache.maven.resolver 63 | maven-resolver-transport-file 64 | 65 | 66 | org.apache.maven.resolver 67 | maven-resolver-transport-http 68 | 69 | 70 | org.apache.maven 71 | maven-resolver-provider 72 | 73 | 74 | org.apache.maven 75 | maven-model-builder 76 | 77 | 78 | org.apache.maven 79 | maven-settings-builder 80 | 81 | 82 | 83 | javax.inject 84 | javax.inject 85 | 86 | 87 | com.google.inject 88 | guice 89 | classes 90 | 91 | 92 | org.eclipse.sisu 93 | org.eclipse.sisu.inject 94 | 95 | 96 | 97 | -------------------------------------------------------------------------------- /runtime/standalone-sisu/src/main/java/eu/maveniverse/maven/mima/runtime/standalonesisu/StandaloneSisuRuntime.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.standalonesisu; 9 | 10 | import eu.maveniverse.maven.mima.context.Context; 11 | import eu.maveniverse.maven.mima.context.ContextOverrides; 12 | import eu.maveniverse.maven.mima.runtime.shared.PreBoot; 13 | import eu.maveniverse.maven.mima.runtime.shared.StandaloneRuntimeSupport; 14 | import eu.maveniverse.maven.mima.runtime.standalonesisu.internal.SisuBooter; 15 | import eu.maveniverse.maven.mima.runtime.standalonesisu.internal.SisuLookup; 16 | import javax.inject.Inject; 17 | import javax.inject.Named; 18 | import javax.inject.Singleton; 19 | import org.apache.maven.model.profile.ProfileSelector; 20 | import org.apache.maven.settings.building.SettingsBuilder; 21 | import org.apache.maven.settings.crypto.SettingsDecrypter; 22 | import org.eclipse.aether.RepositorySystem; 23 | import org.eclipse.sisu.inject.MutableBeanLocator; 24 | 25 | @Singleton 26 | @Named 27 | public final class StandaloneSisuRuntime extends StandaloneRuntimeSupport { 28 | 29 | private final RepositorySystem repositorySystem; 30 | 31 | private final SettingsBuilder settingsBuilder; 32 | 33 | private final SettingsDecrypter settingsDecrypter; 34 | 35 | private final ProfileSelector profileSelector; 36 | 37 | private final MutableBeanLocator locator; 38 | 39 | public StandaloneSisuRuntime() { 40 | this(null, null, null, null, null); 41 | } 42 | 43 | @Inject 44 | public StandaloneSisuRuntime( 45 | RepositorySystem repositorySystem, 46 | SettingsBuilder settingsBuilder, 47 | SettingsDecrypter settingsDecrypter, 48 | ProfileSelector profileSelector, 49 | MutableBeanLocator locator) { 50 | super("standalone-sisu", 30); 51 | this.repositorySystem = repositorySystem; 52 | this.settingsBuilder = settingsBuilder; 53 | this.settingsDecrypter = settingsDecrypter; 54 | this.profileSelector = profileSelector; 55 | this.locator = locator; 56 | } 57 | 58 | @Override 59 | public boolean managedRepositorySystem() { 60 | return repositorySystem == null; 61 | } 62 | 63 | @Override 64 | public Context create(ContextOverrides overrides) { 65 | PreBoot preBoot = preBoot(overrides); 66 | // managed or unmanaged context: depending on how we booted 67 | if (repositorySystem == null) { 68 | SisuBooter booter = SisuBooter.newSisuBooter(preBoot); 69 | return buildContext( 70 | this, 71 | preBoot, 72 | booter.repositorySystem, 73 | booter.settingsBuilder, 74 | booter.settingsDecrypter, 75 | booter.profileSelector, 76 | new SisuLookup(booter.locator), 77 | booter::close); 78 | } else { 79 | return buildContext( 80 | this, 81 | preBoot, 82 | repositorySystem, 83 | settingsBuilder, 84 | settingsDecrypter, 85 | profileSelector, 86 | new SisuLookup(locator), 87 | null); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /extensions/mmr/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.extensions 16 | extensions 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | mmr 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | eu.maveniverse.maven.mima.extensions.mmr 25 | 26 | 27 | 28 | 29 | org.slf4j 30 | slf4j-api 31 | provided 32 | 33 | 34 | eu.maveniverse.maven.mima 35 | context 36 | provided 37 | 38 | 39 | org.apache.maven.resolver 40 | maven-resolver-api 41 | provided 42 | 43 | 44 | org.apache.maven.resolver 45 | maven-resolver-spi 46 | provided 47 | 48 | 49 | org.apache.maven.resolver 50 | maven-resolver-util 51 | provided 52 | 53 | 54 | org.apache.maven 55 | maven-core 56 | provided 57 | 58 | 59 | org.apache.maven 60 | maven-model 61 | provided 62 | 63 | 64 | org.apache.maven 65 | maven-model-builder 66 | provided 67 | 68 | 69 | org.apache.maven 70 | maven-builder-support 71 | provided 72 | 73 | 74 | org.apache.maven 75 | maven-resolver-provider 76 | provided 77 | 78 | 79 | 80 | org.junit.jupiter 81 | junit-jupiter-api 82 | test 83 | 84 | 85 | org.junit.jupiter 86 | junit-jupiter-params 87 | test 88 | 89 | 90 | org.slf4j 91 | slf4j-simple 92 | test 93 | 94 | 95 | eu.maveniverse.maven.mima.runtime 96 | standalone-static 97 | test 98 | 99 | 100 | 101 | -------------------------------------------------------------------------------- /extensions/mhc4/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.extensions 16 | extensions 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | mhc4 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | eu.maveniverse.maven.mima.extensions.mhc4 25 | 26 | 27 | 28 | 29 | org.slf4j 30 | slf4j-api 31 | provided 32 | 33 | 34 | eu.maveniverse.maven.mima 35 | context 36 | provided 37 | 38 | 39 | org.apache.maven.resolver 40 | maven-resolver-api 41 | provided 42 | 43 | 44 | org.apache.maven.resolver 45 | maven-resolver-spi 46 | provided 47 | 48 | 49 | org.apache.maven.resolver 50 | maven-resolver-util 51 | provided 52 | 53 | 54 | 55 | org.apache.httpcomponents 56 | httpclient 57 | provided 58 | 59 | 60 | org.apache.httpcomponents 61 | httpmime 62 | provided 63 | 64 | 65 | org.apache.httpcomponents 66 | httpcore 67 | provided 68 | 69 | 70 | commons-codec 71 | commons-codec 72 | provided 73 | 74 | 75 | org.slf4j 76 | jcl-over-slf4j 77 | provided 78 | 79 | 80 | 81 | org.junit.jupiter 82 | junit-jupiter-api 83 | test 84 | 85 | 86 | org.junit.jupiter 87 | junit-jupiter-params 88 | test 89 | 90 | 91 | org.slf4j 92 | slf4j-simple 93 | test 94 | 95 | 96 | eu.maveniverse.maven.mima.runtime 97 | standalone-static 98 | test 99 | 100 | 101 | 102 | 103 | 104 | 105 | org.apache.maven.plugins 106 | maven-surefire-plugin 107 | 108 | 109 | ${maven.home} 110 | 111 | 112 | 113 | 114 | 115 | 116 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/internal/MavenSystemHomeImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context.internal; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.ContextOverrides; 13 | import eu.maveniverse.maven.mima.context.MavenSystemHome; 14 | import java.nio.file.Path; 15 | import java.util.Objects; 16 | 17 | /** 18 | * Layout of Maven System Home, usually set with {@code $MAVEN_HOME} environment variable, or {@code maven.home} 19 | * Java System Property (by Maven itself). 20 | */ 21 | public final class MavenSystemHomeImpl implements MavenSystemHome { 22 | private final Path mavenSystemHome; 23 | 24 | private final Path settingsXmlOverride; 25 | 26 | private final Path toolchainsXmlOverride; 27 | 28 | public MavenSystemHomeImpl(Path mavenSystemHome) { 29 | this(mavenSystemHome, null, null); 30 | } 31 | 32 | public MavenSystemHomeImpl(Path mavenSystemHome, Path settingsXmlOverride, Path toolchainsXmlOverride) { 33 | this.mavenSystemHome = requireNonNull(mavenSystemHome); 34 | this.settingsXmlOverride = settingsXmlOverride; 35 | this.toolchainsXmlOverride = toolchainsXmlOverride; 36 | } 37 | 38 | @Override 39 | public MavenSystemHomeImpl derive(ContextOverrides contextOverrides) { 40 | return new MavenSystemHomeImpl( 41 | contextOverrides.getMavenSystemHomeOverride() != null 42 | ? contextOverrides.getMavenSystemHomeOverride() 43 | : mavenSystemHome, 44 | contextOverrides.getGlobalSettingsXmlOverride() != null 45 | ? contextOverrides.getGlobalSettingsXmlOverride() 46 | : settingsXmlOverride, 47 | contextOverrides.getGlobalToolchainsXmlOverride() != null 48 | ? contextOverrides.getGlobalToolchainsXmlOverride() 49 | : toolchainsXmlOverride); 50 | } 51 | 52 | @Override 53 | public Path basedir() { 54 | return mavenSystemHome; 55 | } 56 | 57 | @Override 58 | public Path bin() { 59 | return basedir().resolve("bin"); 60 | } 61 | 62 | @Override 63 | public Path boot() { 64 | return basedir().resolve("boot"); 65 | } 66 | 67 | @Override 68 | public Path conf() { 69 | return basedir().resolve("conf"); 70 | } 71 | 72 | @Override 73 | public Path lib() { 74 | return basedir().resolve("lib"); 75 | } 76 | 77 | public Path libExt() { 78 | return lib().resolve("ext"); 79 | } 80 | 81 | @Override 82 | public Path settingsXml() { 83 | if (settingsXmlOverride != null) { 84 | return settingsXmlOverride; 85 | } 86 | return conf().resolve("settings.xml"); 87 | } 88 | 89 | @Override 90 | public Path toolchainsXml() { 91 | if (toolchainsXmlOverride != null) { 92 | return toolchainsXmlOverride; 93 | } 94 | return conf().resolve("toolchains.xml"); 95 | } 96 | 97 | @Override 98 | public boolean equals(Object o) { 99 | if (this == o) { 100 | return true; 101 | } 102 | if (o == null || getClass() != o.getClass()) { 103 | return false; 104 | } 105 | MavenSystemHomeImpl that = (MavenSystemHomeImpl) o; 106 | return Objects.equals(mavenSystemHome, that.mavenSystemHome) 107 | && Objects.equals(settingsXmlOverride, that.settingsXmlOverride) 108 | && Objects.equals(toolchainsXmlOverride, that.toolchainsXmlOverride); 109 | } 110 | 111 | @Override 112 | public int hashCode() { 113 | return Objects.hash(mavenSystemHome, settingsXmlOverride, toolchainsXmlOverride); 114 | } 115 | } 116 | -------------------------------------------------------------------------------- /extensions/mhc4/src/test/java/eu/maveniverse/maven/mima/extensions/mhc4/MavenHttpClient4FactoryTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.extensions.mhc4; 9 | 10 | import eu.maveniverse.maven.mima.context.Context; 11 | import eu.maveniverse.maven.mima.context.ContextOverrides; 12 | import eu.maveniverse.maven.mima.context.Runtimes; 13 | import java.io.IOException; 14 | import java.net.URI; 15 | import org.apache.http.client.methods.CloseableHttpResponse; 16 | import org.apache.http.client.methods.HttpHead; 17 | import org.apache.http.impl.client.CloseableHttpClient; 18 | import org.eclipse.aether.repository.RemoteRepository; 19 | import org.junit.jupiter.api.Assertions; 20 | import org.junit.jupiter.api.Test; 21 | 22 | public class MavenHttpClient4FactoryTest { 23 | private final RemoteRepository httpCentral = 24 | new RemoteRepository.Builder("central-http", "default", "http://repo1.maven.org/maven2/").build(); 25 | 26 | @Test 27 | void deploymentHttps() throws IOException { 28 | try (Context context = Runtimes.INSTANCE 29 | .getRuntime() 30 | .create(ContextOverrides.create().withUserSettings(true).build())) { 31 | MavenHttpClient4Factory factory = new MavenHttpClient4Factory(context); 32 | try (CloseableHttpClient client = 33 | factory.createDeploymentClient(ContextOverrides.CENTRAL).build()) { 34 | try (CloseableHttpResponse response = 35 | client.execute(new HttpHead(URI.create(ContextOverrides.CENTRAL.getUrl()) 36 | .resolve(".meta/prefixes.txt") 37 | .toASCIIString()))) { 38 | Assertions.assertEquals(200, response.getStatusLine().getStatusCode()); 39 | } 40 | } 41 | } 42 | } 43 | 44 | @Test 45 | void deploymentHttp() throws IOException { 46 | try (Context context = Runtimes.INSTANCE 47 | .getRuntime() 48 | .create(ContextOverrides.create().withUserSettings(true).build())) { 49 | MavenHttpClient4Factory factory = new MavenHttpClient4Factory(context); 50 | try (CloseableHttpClient client = 51 | factory.createDeploymentClient(httpCentral).build()) { 52 | try (CloseableHttpResponse response = client.execute(new HttpHead(URI.create(httpCentral.getUrl()) 53 | .resolve(".meta/prefixes.txt") 54 | .toASCIIString()))) { 55 | Assertions.assertEquals(501, response.getStatusLine().getStatusCode()); 56 | } 57 | } 58 | } 59 | } 60 | 61 | @Test 62 | void resolutionHttps() throws IOException { 63 | try (Context context = Runtimes.INSTANCE 64 | .getRuntime() 65 | .create(ContextOverrides.create().withUserSettings(true).build())) { 66 | MavenHttpClient4Factory factory = new MavenHttpClient4Factory(context); 67 | try (CloseableHttpClient client = 68 | factory.createResolutionClient(ContextOverrides.CENTRAL).build()) { 69 | try (CloseableHttpResponse response = 70 | client.execute(new HttpHead(URI.create(ContextOverrides.CENTRAL.getUrl()) 71 | .resolve(".meta/prefixes.txt") 72 | .toASCIIString()))) { 73 | Assertions.assertEquals(200, response.getStatusLine().getStatusCode()); 74 | } 75 | } 76 | } 77 | } 78 | 79 | @Test 80 | void resolutionHttp() { 81 | try (Context context = Runtimes.INSTANCE 82 | .getRuntime() 83 | .create(ContextOverrides.create().withUserSettings(true).build())) { 84 | MavenHttpClient4Factory factory = new MavenHttpClient4Factory(context); 85 | IllegalArgumentException e = Assertions.assertThrows( 86 | IllegalArgumentException.class, () -> factory.createResolutionClient(httpCentral)); 87 | Assertions.assertTrue(e.getMessage().contains("blocked")); 88 | } 89 | } 90 | } 91 | -------------------------------------------------------------------------------- /runtime/standalone-static/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.runtime 16 | runtime 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | standalone-static 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 24 | eu.maveniverse.maven.mima.runtime.standalonestatic 25 | 26 | 27 | 28 | 29 | eu.maveniverse.maven.mima 30 | context 31 | provided 32 | 33 | 34 | eu.maveniverse.maven.mima.runtime 35 | standalone-shared 36 | 37 | 38 | org.apache.maven.resolver 39 | maven-resolver-api 40 | 41 | 42 | org.apache.maven.resolver 43 | maven-resolver-spi 44 | 45 | 46 | org.apache.maven.resolver 47 | maven-resolver-util 48 | 49 | 50 | org.apache.maven.resolver 51 | maven-resolver-connector-basic 52 | 53 | 54 | org.apache.maven.resolver 55 | maven-resolver-named-locks 56 | 57 | 58 | org.apache.maven.resolver 59 | maven-resolver-impl 60 | 61 | 62 | org.apache.maven.resolver 63 | maven-resolver-transport-file 64 | 65 | 66 | org.apache.maven.resolver 67 | maven-resolver-transport-http 68 | 69 | 70 | org.apache.maven.resolver 71 | maven-resolver-supplier 72 | 73 | 74 | org.apache.maven 75 | maven-resolver-provider 76 | 77 | 78 | javax.inject 79 | javax.inject 80 | 81 | 82 | org.eclipse.sisu 83 | org.eclipse.sisu.inject 84 | 85 | 86 | 87 | 88 | org.apache.maven 89 | maven-model-builder 90 | 91 | 92 | javax.inject 93 | javax.inject 94 | 95 | 96 | org.eclipse.sisu 97 | org.eclipse.sisu.inject 98 | 99 | 100 | 101 | 102 | org.apache.maven 103 | maven-settings-builder 104 | 105 | 106 | javax.inject 107 | javax.inject 108 | 109 | 110 | org.eclipse.sisu 111 | org.eclipse.sisu.inject 112 | 113 | 114 | 115 | 116 | 117 | -------------------------------------------------------------------------------- /extensions/mmr/src/main/java/eu/maveniverse/maven/mima/extensions/mmr/ModelResponse.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.extensions.mmr; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import java.util.List; 13 | import java.util.function.Function; 14 | import org.apache.maven.model.Model; 15 | import org.eclipse.aether.repository.ArtifactRepository; 16 | import org.eclipse.aether.resolution.ArtifactDescriptorResult; 17 | 18 | /** 19 | * Model response carries models (raw and effective) but also offers some tools within the context of the read model. 20 | *

21 | * One example would be something similar like done in Toolbox: getting raw model, modify it, interpolate it and finally 22 | * transform it to {@link ArtifactDescriptorResult} for friendlier after-processing in Resolver. 23 | */ 24 | public class ModelResponse { 25 | private final Model rawModel; 26 | private final Model effectiveModel; 27 | private final ArtifactRepository repository; 28 | private final Function converter; 29 | private final List lineage; 30 | private final Function lineageFunction; 31 | private final Function interpolatorFunction; 32 | 33 | public ModelResponse( 34 | Model rawModel, 35 | Model effectiveModel, 36 | ArtifactRepository repository, 37 | Function converter, 38 | List lineage, 39 | Function lineageFunction, 40 | Function interpolatorFunction) { 41 | this.rawModel = requireNonNull(rawModel); 42 | this.effectiveModel = requireNonNull(effectiveModel); 43 | this.repository = repository; 44 | this.converter = requireNonNull(converter); 45 | this.lineage = requireNonNull(lineage); 46 | this.lineageFunction = requireNonNull(lineageFunction); 47 | this.interpolatorFunction = requireNonNull(interpolatorFunction); 48 | } 49 | 50 | /** 51 | * Returns the built effective model. 52 | *

53 | * If you intend to modify model but need to keep "original" as well, use method {@link Model#clone()} to clone the 54 | * model instance, otherwise you will end up with modified model in this result instance. 55 | */ 56 | public Model getEffectiveModel() { 57 | return effectiveModel; 58 | } 59 | 60 | /** 61 | * Returns the "raw" (as is on disk) model. 62 | *

63 | * If you intend to modify model but need to keep "original" as well, use method {@link Model#clone()} to clone the 64 | * model instance, otherwise you will end up with modified model in this result instance. 65 | */ 66 | public Model getRawModel() { 67 | return rawModel; 68 | } 69 | 70 | /** 71 | * Gets the repository from which the descriptor was eventually resolved or {@code null} if unknown. 72 | */ 73 | public ArtifactRepository getRepository() { 74 | return repository; 75 | } 76 | 77 | /** 78 | * Returns artifact descriptor result of given model. 79 | */ 80 | public ArtifactDescriptorResult toArtifactDescriptorResult(Model model) { 81 | requireNonNull(model); 82 | return converter.apply(model); 83 | } 84 | 85 | /** 86 | * Returns the model "lineage" keys, first in list represents "current" model, last the Super POM, and parents in 87 | * middle. 88 | */ 89 | public List getLineage() { 90 | return lineage; 91 | } 92 | 93 | /** 94 | * Returns RAW model with given key (that is string concatenated as {@code groupId:artifactId:versionId}). 95 | * 96 | * @see #getLineage() 97 | */ 98 | public Model getLineageModel(String modelId) { 99 | return lineageFunction.apply(modelId); 100 | } 101 | 102 | /** 103 | * Interpolates model. Make sense only on non-effective models, as effective models are already interpolated. 104 | * Uses value set provided by this "current" model. The model is first cloned, then interpolated, so the returned 105 | * instance is not the same instance as the passed in. 106 | */ 107 | public Model interpolateModel(Model model) { 108 | return interpolatorFunction.apply(model); 109 | } 110 | } 111 | -------------------------------------------------------------------------------- /demo/library-standalone-sisu/src/test/java/eu/maveniverse/maven/mima/impl/library/ClasspathTest.java: -------------------------------------------------------------------------------- 1 | package eu.maveniverse.maven.mima.impl.library; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNotNull; 5 | import static org.junit.jupiter.api.Assertions.assertThrows; 6 | 7 | import eu.maveniverse.maven.mima.context.Context; 8 | import eu.maveniverse.maven.mima.context.ContextOverrides; 9 | import eu.maveniverse.maven.mima.context.Runtimes; 10 | import java.nio.file.Paths; 11 | import org.eclipse.aether.repository.Authentication; 12 | import org.eclipse.aether.repository.AuthenticationContext; 13 | import org.eclipse.aether.repository.RemoteRepository; 14 | import org.eclipse.aether.resolution.DependencyResolutionException; 15 | import org.junit.jupiter.api.Test; 16 | 17 | public class ClasspathTest { 18 | @Test 19 | public void simpleModel() throws Exception { 20 | ContextOverrides overrides = ContextOverrides.create() 21 | .withLocalRepositoryOverride(Paths.get("target/simple-model")) 22 | .build(); 23 | 24 | String cp = new Classpath().model(overrides, "junit:junit:4.13.2"); 25 | assertNotNull(cp); 26 | } 27 | 28 | @Test 29 | public void simpleClasspath() throws Exception { 30 | ContextOverrides overrides = ContextOverrides.create() 31 | .withLocalRepositoryOverride(Paths.get("target/simple-classpath")) 32 | .build(); 33 | 34 | String cp = new Classpath().classpath(overrides, "junit:junit:4.13.2"); 35 | assertNotNull(cp); 36 | } 37 | 38 | @Test 39 | public void simpleOfflineClasspath() { 40 | ContextOverrides overrides = ContextOverrides.create() 41 | .withLocalRepositoryOverride(Paths.get("target/simple-classpath-offline")) 42 | .offline(true) 43 | .build(); 44 | 45 | assertThrows( 46 | DependencyResolutionException.class, () -> new Classpath().classpath(overrides, "junit:junit:4.13.2")); 47 | } 48 | 49 | @Test 50 | public void simpleEncrypted() { 51 | ContextOverrides overrides = ContextOverrides.create() 52 | .withMavenUserHomeOverride(Paths.get("target/test-classes/encrypted")) 53 | .withUserSettings(true) 54 | .withLocalRepositoryOverride(Paths.get("target/simpleEncrypted")) 55 | .build(); 56 | 57 | try (Context context = Runtimes.INSTANCE.getRuntime().create(overrides)) { 58 | RemoteRepository repository = context.repositorySystem() 59 | .newDeploymentRepository( 60 | context.repositorySystemSession(), 61 | new RemoteRepository.Builder("my-server", "default", "https://does.not.matter/").build()); 62 | Authentication authentication = repository.getAuthentication(); 63 | try (AuthenticationContext authContext = 64 | AuthenticationContext.forRepository(context.repositorySystemSession(), repository)) { 65 | authentication.fill(authContext, AuthenticationContext.PASSWORD, null); 66 | String pw = authContext.get(AuthenticationContext.PASSWORD); 67 | assertEquals(pw, "server-secret"); 68 | } 69 | } 70 | } 71 | 72 | @Test 73 | public void simpleEncryptedNoMaster() { 74 | ContextOverrides overrides = ContextOverrides.create() 75 | .withMavenUserHomeOverride(Paths.get("target/test-classes/encrypted")) 76 | .withUserSettingsSecurityXmlOverride(Paths.get("no-such-file")) 77 | .withUserSettings(true) 78 | .withLocalRepositoryOverride(Paths.get("target/simpleEncrypted")) 79 | .build(); 80 | 81 | try (Context context = Runtimes.INSTANCE.getRuntime().create(overrides)) { 82 | RemoteRepository repository = context.repositorySystem() 83 | .newDeploymentRepository( 84 | context.repositorySystemSession(), 85 | new RemoteRepository.Builder("my-server", "default", "https://does.not.matter/").build()); 86 | Authentication authentication = repository.getAuthentication(); 87 | try (AuthenticationContext authContext = 88 | AuthenticationContext.forRepository(context.repositorySystemSession(), repository)) { 89 | authentication.fill(authContext, AuthenticationContext.PASSWORD, null); 90 | String pw = authContext.get(AuthenticationContext.PASSWORD); 91 | assertEquals(pw, "{BnJray6RajsHJ1EO0G6owUQBV3DNG/bWKiyipdTKeyA=}"); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /demo/library-standalone-static/src/test/java/eu/maveniverse/maven/mima/impl/library/ClasspathTest.java: -------------------------------------------------------------------------------- 1 | package eu.maveniverse.maven.mima.impl.library; 2 | 3 | import static org.junit.jupiter.api.Assertions.assertEquals; 4 | import static org.junit.jupiter.api.Assertions.assertNotNull; 5 | import static org.junit.jupiter.api.Assertions.assertThrows; 6 | 7 | import eu.maveniverse.maven.mima.context.Context; 8 | import eu.maveniverse.maven.mima.context.ContextOverrides; 9 | import eu.maveniverse.maven.mima.context.Runtimes; 10 | import java.nio.file.Paths; 11 | import org.eclipse.aether.repository.Authentication; 12 | import org.eclipse.aether.repository.AuthenticationContext; 13 | import org.eclipse.aether.repository.RemoteRepository; 14 | import org.eclipse.aether.resolution.DependencyResolutionException; 15 | import org.junit.jupiter.api.Test; 16 | 17 | public class ClasspathTest { 18 | @Test 19 | public void simpleModel() throws Exception { 20 | ContextOverrides overrides = ContextOverrides.create() 21 | .withLocalRepositoryOverride(Paths.get("target/simple-model")) 22 | .build(); 23 | 24 | String cp = new Classpath().model(overrides, "junit:junit:4.13.2"); 25 | assertNotNull(cp); 26 | } 27 | 28 | @Test 29 | public void simpleClasspath() throws Exception { 30 | ContextOverrides overrides = ContextOverrides.create() 31 | .withLocalRepositoryOverride(Paths.get("target/simple-classpath")) 32 | .build(); 33 | 34 | String cp = new Classpath().classpath(overrides, "junit:junit:4.13.2"); 35 | assertNotNull(cp); 36 | } 37 | 38 | @Test 39 | public void simpleOfflineClasspath() { 40 | ContextOverrides overrides = ContextOverrides.create() 41 | .withLocalRepositoryOverride(Paths.get("target/simple-classpath-offline")) 42 | .offline(true) 43 | .build(); 44 | 45 | assertThrows( 46 | DependencyResolutionException.class, () -> new Classpath().classpath(overrides, "junit:junit:4.13.2")); 47 | } 48 | 49 | @Test 50 | public void simpleEncrypted() { 51 | ContextOverrides overrides = ContextOverrides.create() 52 | .withMavenUserHomeOverride(Paths.get("target/test-classes/encrypted")) 53 | .withUserSettings(true) 54 | .withLocalRepositoryOverride(Paths.get("target/simpleEncrypted")) 55 | .build(); 56 | 57 | try (Context context = Runtimes.INSTANCE.getRuntime().create(overrides)) { 58 | RemoteRepository repository = context.repositorySystem() 59 | .newDeploymentRepository( 60 | context.repositorySystemSession(), 61 | new RemoteRepository.Builder("my-server", "default", "https://does.not.matter/").build()); 62 | Authentication authentication = repository.getAuthentication(); 63 | try (AuthenticationContext authContext = 64 | AuthenticationContext.forRepository(context.repositorySystemSession(), repository)) { 65 | authentication.fill(authContext, AuthenticationContext.PASSWORD, null); 66 | String pw = authContext.get(AuthenticationContext.PASSWORD); 67 | assertEquals(pw, "server-secret"); 68 | } 69 | } 70 | } 71 | 72 | @Test 73 | public void simpleEncryptedNoMaster() { 74 | ContextOverrides overrides = ContextOverrides.create() 75 | .withMavenUserHomeOverride(Paths.get("target/test-classes/encrypted")) 76 | .withUserSettingsSecurityXmlOverride(Paths.get("no-such-file")) 77 | .withUserSettings(true) 78 | .withLocalRepositoryOverride(Paths.get("target/simpleEncrypted")) 79 | .build(); 80 | 81 | try (Context context = Runtimes.INSTANCE.getRuntime().create(overrides)) { 82 | RemoteRepository repository = context.repositorySystem() 83 | .newDeploymentRepository( 84 | context.repositorySystemSession(), 85 | new RemoteRepository.Builder("my-server", "default", "https://does.not.matter/").build()); 86 | Authentication authentication = repository.getAuthentication(); 87 | try (AuthenticationContext authContext = 88 | AuthenticationContext.forRepository(context.repositorySystemSession(), repository)) { 89 | authentication.fill(authContext, AuthenticationContext.PASSWORD, null); 90 | String pw = authContext.get(AuthenticationContext.PASSWORD); 91 | assertEquals(pw, "{BnJray6RajsHJ1EO0G6owUQBV3DNG/bWKiyipdTKeyA=}"); 92 | } 93 | } 94 | } 95 | } 96 | -------------------------------------------------------------------------------- /extensions/mmr/src/main/java/eu/maveniverse/maven/mima/extensions/mmr/ModelRequest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.extensions.mmr; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import java.nio.file.Path; 13 | import java.util.ArrayList; 14 | import java.util.Collections; 15 | import java.util.List; 16 | import org.eclipse.aether.RequestTrace; 17 | import org.eclipse.aether.artifact.Artifact; 18 | import org.eclipse.aether.artifact.DefaultArtifact; 19 | import org.eclipse.aether.repository.RemoteRepository; 20 | 21 | /** 22 | * Model request. 23 | */ 24 | public class ModelRequest { 25 | public static Builder builder() { 26 | return new Builder(); 27 | } 28 | 29 | private final Artifact artifact; 30 | private final List repositories; 31 | private final String requestContext; 32 | private final RequestTrace trace; 33 | 34 | private ModelRequest( 35 | Artifact artifact, List repositories, String requestContext, RequestTrace trace) { 36 | this.artifact = requireNonNull(artifact); 37 | this.requestContext = requestContext == null ? "" : requestContext; 38 | this.trace = trace; 39 | this.repositories = repositories; 40 | } 41 | 42 | public Artifact getArtifact() { 43 | return artifact; 44 | } 45 | 46 | public List getRepositories() { 47 | return repositories; 48 | } 49 | 50 | public String getRequestContext() { 51 | return requestContext; 52 | } 53 | 54 | public RequestTrace getTrace() { 55 | return trace; 56 | } 57 | 58 | public Builder toBuilder() { 59 | return new Builder(this); 60 | } 61 | 62 | public static class Builder { 63 | private Artifact artifact; 64 | private List repositories; 65 | private String requestContext; 66 | private RequestTrace trace; 67 | 68 | private Builder() {} 69 | 70 | private Builder(ModelRequest request) { 71 | this.artifact = request.artifact; 72 | this.repositories = request.repositories; 73 | this.requestContext = request.requestContext; 74 | this.trace = request.trace; 75 | } 76 | 77 | public ModelRequest build() { 78 | return new ModelRequest( 79 | artifact, 80 | repositories != null ? Collections.unmodifiableList(new ArrayList<>(repositories)) : null, 81 | requestContext, 82 | trace); 83 | } 84 | 85 | /** 86 | * Make possible to point at a POM anywhere on file system, to have it built. Naturally, all the required 87 | * bits like parent POM, imported POM must be still resolvable (from local or remote repositories). 88 | */ 89 | public Builder setPomFile(Path pomFile) { 90 | requireNonNull(pomFile); 91 | return setArtifact(new DefaultArtifact("irrelevant:irrelevant:irrelevant").setFile(pomFile.toFile())); 92 | } 93 | 94 | /** 95 | * Sets the artifact whose POM we want to build model for. The artifact must be resolvable from local or 96 | * remote repositories. 97 | */ 98 | public Builder setArtifact(Artifact artifact) { 99 | requireNonNull(artifact); 100 | this.artifact = artifact; 101 | return this; 102 | } 103 | 104 | /** 105 | * Optionally, user may want to override context "root" repositories with own set (ie appended or totally new 106 | * list of repositories). 107 | */ 108 | public Builder setRepositories(List repositories) { 109 | this.repositories = repositories; 110 | return this; 111 | } 112 | 113 | /** 114 | * Sets the request context for bookkeeping purposes. 115 | */ 116 | public Builder setRequestContext(String requestContext) { 117 | this.requestContext = requestContext; 118 | return this; 119 | } 120 | 121 | /** 122 | * Sets the request trace for bookkeeping purposes. 123 | */ 124 | public Builder setTrace(RequestTrace trace) { 125 | this.trace = trace; 126 | return this; 127 | } 128 | } 129 | } 130 | -------------------------------------------------------------------------------- /extensions/mmr/src/main/java/eu/maveniverse/maven/mima/extensions/mmr/MavenModelReader.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.extensions.mmr; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.Context; 13 | import eu.maveniverse.maven.mima.extensions.mmr.internal.MavenModelReaderImpl; 14 | import org.apache.maven.model.building.ModelBuilder; 15 | import org.apache.maven.model.interpolation.StringVisitorModelInterpolator; 16 | import org.eclipse.aether.RepositorySystemSession; 17 | import org.eclipse.aether.artifact.Artifact; 18 | import org.eclipse.aether.impl.RemoteRepositoryManager; 19 | import org.eclipse.aether.impl.RepositoryEventDispatcher; 20 | import org.eclipse.aether.resolution.ArtifactDescriptorException; 21 | import org.eclipse.aether.resolution.ArtifactResolutionException; 22 | import org.eclipse.aether.resolution.VersionResolutionException; 23 | import org.slf4j.Logger; 24 | import org.slf4j.LoggerFactory; 25 | 26 | /** 27 | * Maven Model Reader, an extension that is able to read POM Models at various levels. 28 | *

29 | * This component resembles {@link org.eclipse.aether.RepositorySystem#readArtifactDescriptor(RepositorySystemSession, org.eclipse.aether.resolution.ArtifactDescriptorRequest)} 30 | * somewhat, but have notable differences: 31 | *

41 | * The purpose of this extension is to provide insight into Maven models without the need to fiddle 42 | * with any of those things like Model builder and so on. Usages like some "analysis" or "introspection" 43 | * or "validation" come to mind for start. 44 | *

45 | * Note: this extension and all classes in it are EXPERIMENTAL, use on your own risk! 46 | */ 47 | public class MavenModelReader { 48 | private final Logger logger = LoggerFactory.getLogger(getClass()); 49 | private final Context context; 50 | private final MavenModelReaderImpl mavenModelReaderImpl; 51 | 52 | /** 53 | * Creates instance using passed in context. As context carries "root" remote repositories, they are used 54 | * by default, but can be overridden in {@link ModelRequest}. 55 | */ 56 | public MavenModelReader(Context context) { 57 | this.context = requireNonNull(context); 58 | this.mavenModelReaderImpl = new MavenModelReaderImpl( 59 | context.repositorySystem(), 60 | context.lookup() 61 | .lookup(RemoteRepositoryManager.class) 62 | .orElseThrow(() -> new IllegalStateException("RemoteRepositoryManager not available")), 63 | context.lookup() 64 | .lookup(RepositoryEventDispatcher.class) 65 | .orElseThrow(() -> new IllegalStateException("RepositoryEventDispatcher not available")), 66 | context.lookup() 67 | .lookup(ModelBuilder.class) 68 | .orElseThrow(() -> new IllegalStateException("ModelBuilder not available")), 69 | context.lookup() 70 | .lookup(StringVisitorModelInterpolator.class) 71 | .orElseThrow(() -> new IllegalStateException("StringVisitorModelInterpolator not available")), 72 | context.remoteRepositories()); 73 | } 74 | 75 | /** 76 | * Reads POM as {@link ModelResponse}. 77 | *

78 | * Remark related to repositories: by default context "root" remote repositories will be used, unless 79 | * request {@link ModelRequest#getRepositories()} returns non-null value, in which case request provided 80 | * repositories will be used. 81 | */ 82 | public ModelResponse readModel(ModelRequest request) 83 | throws VersionResolutionException, ArtifactResolutionException, ArtifactDescriptorException { 84 | requireNonNull(request, "request"); 85 | return mavenModelReaderImpl.readModel(context.repositorySystemSession(), request); 86 | } 87 | 88 | /** 89 | * Just to allow easier testing. 90 | */ 91 | public MavenModelReaderImpl getImpl() { 92 | return mavenModelReaderImpl; 93 | } 94 | } 95 | -------------------------------------------------------------------------------- /runtime/standalone-sisu-uber/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.runtime 16 | runtime 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | standalone-sisu-uber 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 25 | 26 | 27 | eu.maveniverse.maven.mima.runtime.standalonesisu 28 | 29 | 30 | 31 | 32 | eu.maveniverse.maven.mima 33 | context 34 | provided 35 | 36 | 37 | eu.maveniverse.maven.mima.runtime 38 | standalone-sisu 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-shade-plugin 47 | 48 | ${project.build.directory}/dependency-reduced-pom.xml 49 | 50 | 51 | org.slf4j:* 52 | 53 | 54 | 55 | 56 | *:* 57 | 58 | META-INF/DEPENDENCIES 59 | META-INF/LICENSE 60 | META-INF/LICENSE.txt 61 | META-INF/MANIFEST.MF 62 | META-INF/NOTICE 63 | META-INF/NOTICE.txt 64 | META-INF/services/javax.annotation.processing.Processor 65 | **/module-info.class 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | shade 79 | 80 | package 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-source-plugin 87 | 88 | true 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-dependency-plugin 94 | 95 | 96 | source-dependencies 97 | 98 | unpack-dependencies 99 | 100 | prepare-package 101 | 102 | sources 103 | false 104 | ${project.build.directory}/sources 105 | org.slf4j 106 | **/*.java 107 | runtime 108 | 109 | 110 | 111 | 112 | 113 | org.apache.maven.plugins 114 | maven-assembly-plugin 115 | 116 | 117 | uber-source 118 | 119 | single 120 | 121 | package 122 | 123 | 124 | ${project.basedir}/src/assemblies/uber-source.xml 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /runtime/standalone-static-uber/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.mima.runtime 16 | runtime 17 | 2.4.40-SNAPSHOT 18 | 19 | 20 | standalone-static-uber 21 | ${project.groupId}:${project.artifactId} 22 | 23 | 25 | 26 | 27 | eu.maveniverse.maven.mima.runtime.standalonestatic 28 | 29 | 30 | 31 | 32 | eu.maveniverse.maven.mima 33 | context 34 | provided 35 | 36 | 37 | eu.maveniverse.maven.mima.runtime 38 | standalone-static 39 | 40 | 41 | 42 | 43 | 44 | 45 | org.apache.maven.plugins 46 | maven-shade-plugin 47 | 48 | ${project.build.directory}/dependency-reduced-pom.xml 49 | 50 | 51 | org.slf4j:* 52 | 53 | 54 | 55 | 56 | *:* 57 | 58 | META-INF/DEPENDENCIES 59 | META-INF/LICENSE 60 | META-INF/LICENSE.txt 61 | META-INF/MANIFEST.MF 62 | META-INF/NOTICE 63 | META-INF/NOTICE.txt 64 | META-INF/services/javax.annotation.processing.Processor 65 | **/module-info.class 66 | 67 | 68 | 69 | 70 | 71 | 72 | 73 | 74 | 75 | 76 | 77 | 78 | shade 79 | 80 | package 81 | 82 | 83 | 84 | 85 | org.apache.maven.plugins 86 | maven-source-plugin 87 | 88 | true 89 | 90 | 91 | 92 | org.apache.maven.plugins 93 | maven-dependency-plugin 94 | 95 | 96 | source-dependencies 97 | 98 | unpack-dependencies 99 | 100 | prepare-package 101 | 102 | sources 103 | false 104 | ${project.build.directory}/sources 105 | org.slf4j 106 | **/*.java 107 | runtime 108 | 109 | 110 | 111 | 112 | 113 | org.apache.maven.plugins 114 | maven-assembly-plugin 115 | 116 | 117 | uber-source 118 | 119 | single 120 | 121 | package 122 | 123 | 124 | ${project.basedir}/src/assemblies/uber-source.xml 125 | 126 | 127 | 128 | 129 | 130 | 131 | 132 | 133 | -------------------------------------------------------------------------------- /extensions/mmr/src/test/java/eu/maveniverse/maven/mima/extensions/mmr/MavenModelReaderTest.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.extensions.mmr; 9 | 10 | import static org.junit.jupiter.api.Assertions.assertEquals; 11 | import static org.junit.jupiter.api.Assertions.assertNotNull; 12 | import static org.junit.jupiter.api.Assertions.assertNull; 13 | 14 | import eu.maveniverse.maven.mima.context.Context; 15 | import eu.maveniverse.maven.mima.context.ContextOverrides; 16 | import eu.maveniverse.maven.mima.context.Runtimes; 17 | import java.util.Arrays; 18 | import java.util.Collections; 19 | import java.util.stream.Stream; 20 | import org.apache.maven.model.Model; 21 | import org.eclipse.aether.artifact.Artifact; 22 | import org.eclipse.aether.artifact.DefaultArtifact; 23 | import org.eclipse.aether.repository.ArtifactRepository; 24 | import org.eclipse.aether.repository.RemoteRepository; 25 | import org.eclipse.aether.resolution.ArtifactDescriptorResult; 26 | import org.junit.jupiter.params.ParameterizedTest; 27 | import org.junit.jupiter.params.provider.MethodSource; 28 | 29 | public class MavenModelReaderTest { 30 | private static Stream repositories() { 31 | return Arrays.stream(new RemoteRepository[] { 32 | null, // context 33 | ContextOverrides.CENTRAL, // central override 34 | new RemoteRepository.Builder("foobar", "default", "https://repo1.maven.org/maven2").build() // alt central 35 | }); 36 | } 37 | 38 | @ParameterizedTest 39 | @MethodSource("repositories") 40 | void smoke(RemoteRepository overrideRepository) throws Exception { 41 | try (Context context = 42 | Runtimes.INSTANCE.getRuntime().create(ContextOverrides.create().build())) { 43 | MavenModelReader reader = new MavenModelReader(context); 44 | 45 | ModelResponse response = reader.readModel(ModelRequest.builder() 46 | .setArtifact(new DefaultArtifact("org.apache.maven:maven-core:3.9.9")) 47 | .setRepositories(overrideRepository != null ? Collections.singletonList(overrideRepository) : null) 48 | .setRequestContext("test") 49 | .build()); 50 | assertNotNull(response); 51 | Model model; 52 | 53 | // REPO 54 | ArtifactRepository responseRepository = response.getRepository(); 55 | if (overrideRepository == null) { 56 | assertEquals(context.remoteRepositories().get(0), responseRepository); 57 | } else { 58 | assertEquals(overrideRepository, responseRepository); 59 | } 60 | 61 | // RAW 62 | model = response.getRawModel(); 63 | assertNotNull(model); 64 | assertNull(model.getGroupId()); 65 | assertEquals("maven-core", model.getArtifactId()); 66 | assertNull(model.getVersion()); 67 | assertNull(model.getUrl()); 68 | 69 | // Effective 70 | model = response.getEffectiveModel(); 71 | assertNotNull(model); 72 | assertEquals("org.apache.maven", model.getGroupId()); 73 | assertEquals("maven-core", model.getArtifactId()); 74 | assertEquals("3.9.9", model.getVersion()); 75 | assertEquals("https://maven.apache.org/ref/3.9.9/maven-core/", model.getUrl()); 76 | 77 | ArtifactDescriptorResult result; 78 | Artifact artifact; 79 | // ADR out of RAW 80 | result = response.toArtifactDescriptorResult(response.interpolateModel(response.getRawModel())); 81 | // we cannot compare this RESOLVED artifact (has file and properties) 82 | artifact = result.getArtifact(); 83 | assertEquals( 84 | new DefaultArtifact( 85 | artifact.getGroupId(), 86 | artifact.getArtifactId(), 87 | artifact.getExtension(), 88 | artifact.getVersion()), 89 | new DefaultArtifact("org.apache.maven:maven-core:3.9.9")); 90 | assertEquals(28, result.getDependencies().size()); 91 | assertEquals(0, result.getManagedDependencies().size()); 92 | 93 | // ADR out of EFFECTIVE 94 | result = response.toArtifactDescriptorResult(response.getEffectiveModel()); 95 | // we cannot compare this RESOLVED artifact (has file and properties) 96 | artifact = result.getArtifact(); 97 | assertEquals( 98 | new DefaultArtifact( 99 | artifact.getGroupId(), 100 | artifact.getArtifactId(), 101 | artifact.getExtension(), 102 | artifact.getVersion()), 103 | new DefaultArtifact("org.apache.maven:maven-core:3.9.9")); 104 | assertEquals(30, result.getDependencies().size()); 105 | assertEquals(74, result.getManagedDependencies().size()); 106 | } 107 | } 108 | } 109 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/internal/MavenUserHomeImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context.internal; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.ContextOverrides; 13 | import eu.maveniverse.maven.mima.context.MavenUserHome; 14 | import java.nio.file.Path; 15 | import java.util.Objects; 16 | 17 | /** 18 | * Layout of Maven User Home, by default {@code $HOME/.m2}. 19 | */ 20 | public final class MavenUserHomeImpl implements MavenUserHome { 21 | private final Path mavenUserHome; 22 | 23 | private final Path settingsXmlOverride; 24 | 25 | private final Path settingsSecurityXmlOverride; 26 | 27 | private final Path toolchainsXmlOverride; 28 | 29 | private final Path localRepositoryOverride; 30 | 31 | public MavenUserHomeImpl(Path mavenUserHome) { 32 | this(mavenUserHome, null, null, null, null); 33 | } 34 | 35 | public MavenUserHomeImpl( 36 | Path mavenUserHome, 37 | Path settingsXmlOverride, 38 | Path settingsSecurityXmlOverride, 39 | Path toolchainsXmlOverride, 40 | Path localRepositoryOverride) { 41 | this.mavenUserHome = requireNonNull(mavenUserHome); 42 | this.settingsXmlOverride = settingsXmlOverride; 43 | this.settingsSecurityXmlOverride = settingsSecurityXmlOverride; 44 | this.toolchainsXmlOverride = toolchainsXmlOverride; 45 | this.localRepositoryOverride = localRepositoryOverride; 46 | } 47 | 48 | public MavenUserHomeImpl withLocalRepository(Path localRepository) { 49 | return new MavenUserHomeImpl( 50 | mavenUserHome, 51 | settingsXmlOverride, 52 | settingsSecurityXmlOverride, 53 | toolchainsXmlOverride, 54 | localRepository); 55 | } 56 | 57 | @Override 58 | public MavenUserHomeImpl derive(ContextOverrides contextOverrides) { 59 | return new MavenUserHomeImpl( 60 | contextOverrides.getMavenUserHomeOverride() != null 61 | ? contextOverrides.getMavenUserHomeOverride() 62 | : mavenUserHome, 63 | contextOverrides.getUserSettingsXmlOverride() != null 64 | ? contextOverrides.getUserSettingsXmlOverride() 65 | : settingsXmlOverride, 66 | contextOverrides.getUserSettingsSecurityXmlOverride() != null 67 | ? contextOverrides.getUserSettingsSecurityXmlOverride() 68 | : settingsSecurityXmlOverride, 69 | contextOverrides.getUserToolchainsXmlOverride() != null 70 | ? contextOverrides.getUserToolchainsXmlOverride() 71 | : toolchainsXmlOverride, 72 | contextOverrides.getLocalRepositoryOverride() != null 73 | ? contextOverrides.getLocalRepositoryOverride() 74 | : localRepositoryOverride); 75 | } 76 | 77 | @Override 78 | public Path basedir() { 79 | return mavenUserHome; 80 | } 81 | 82 | @Override 83 | public Path settingsXml() { 84 | if (settingsXmlOverride != null) { 85 | return settingsXmlOverride; 86 | } 87 | return basedir().resolve("settings.xml"); 88 | } 89 | 90 | @Override 91 | public Path settingsSecurityXml() { 92 | if (settingsSecurityXmlOverride != null) { 93 | return settingsSecurityXmlOverride; 94 | } 95 | return basedir().resolve("settings-security.xml"); 96 | } 97 | 98 | @Override 99 | public Path toolchainsXml() { 100 | if (toolchainsXmlOverride != null) { 101 | return toolchainsXmlOverride; 102 | } 103 | return basedir().resolve("toolchains.xml"); 104 | } 105 | 106 | @Override 107 | public Path localRepository() { 108 | if (localRepositoryOverride != null) { 109 | return localRepositoryOverride; 110 | } 111 | return basedir().resolve("repository"); 112 | } 113 | 114 | @Override 115 | public boolean equals(Object o) { 116 | if (this == o) { 117 | return true; 118 | } 119 | if (o == null || getClass() != o.getClass()) { 120 | return false; 121 | } 122 | MavenUserHomeImpl that = (MavenUserHomeImpl) o; 123 | return Objects.equals(mavenUserHome, that.mavenUserHome) 124 | && Objects.equals(settingsXmlOverride, that.settingsXmlOverride) 125 | && Objects.equals(settingsSecurityXmlOverride, that.settingsSecurityXmlOverride) 126 | && Objects.equals(toolchainsXmlOverride, that.toolchainsXmlOverride) 127 | && Objects.equals(localRepositoryOverride, that.localRepositoryOverride); 128 | } 129 | 130 | @Override 131 | public int hashCode() { 132 | return Objects.hash( 133 | mavenUserHome, 134 | settingsXmlOverride, 135 | settingsSecurityXmlOverride, 136 | toolchainsXmlOverride, 137 | localRepositoryOverride); 138 | } 139 | } 140 | -------------------------------------------------------------------------------- /demo/pom.xml: -------------------------------------------------------------------------------- 1 | 2 | 11 | 12 | 4.0.0 13 | 14 | 15 | eu.maveniverse.maven.parent 16 | parent 17 | 49 18 | 19 | 20 | 21 | eu.maveniverse.maven.mima.demo 22 | demo 23 | 1.0.0-SNAPSHOT 24 | pom 25 | ${project.groupId}:${project.artifactId} 26 | 27 | 28 | library 29 | library-standalone-sisu 30 | library-standalone-static 31 | library-maven-plugin 32 | 33 | 34 | 35 | 2.4.40-SNAPSHOT 36 | 37 | 1.7.36 38 | 3.9.12 39 | 1.9.25 40 | 41 | UTF-8 42 | UTF-8 43 | 44 | 45 | true 46 | 47 | 48 | [3.6.3,) 49 | [8,) 50 | 51 | 52 | 8 53 | 8 54 | 57 | true 58 | false 59 | 600 60 | false 61 | 62 | 63 | 64 | 65 | 66 | 67 | eu.maveniverse.maven.mima.demo 68 | library 69 | ${project.version} 70 | 71 | 72 | 73 | eu.maveniverse.maven.mima 74 | context 75 | ${version.mima} 76 | 77 | 78 | eu.maveniverse.maven.mima.runtime 79 | embedded-maven 80 | ${version.mima} 81 | 82 | 83 | eu.maveniverse.maven.mima.runtime 84 | standalone-sisu 85 | ${version.mima} 86 | 87 | 88 | eu.maveniverse.maven.mima.runtime 89 | standalone-sisu-uber 90 | ${version.mima} 91 | 92 | 93 | eu.maveniverse.maven.mima.runtime 94 | standalone-static 95 | ${version.mima} 96 | 97 | 98 | eu.maveniverse.maven.mima.runtime 99 | standalone-static-uber 100 | ${version.mima} 101 | 102 | 103 | eu.maveniverse.maven.mima.extensions 104 | mmr 105 | ${version.mima} 106 | 107 | 108 | 109 | org.slf4j 110 | slf4j-api 111 | ${version.slf4j} 112 | 113 | 114 | org.slf4j 115 | jcl-over-slf4j 116 | ${version.slf4j} 117 | 118 | 119 | org.slf4j 120 | slf4j-simple 121 | ${version.slf4j} 122 | 123 | 124 | 125 | org.junit.jupiter 126 | junit-jupiter-api 127 | 5.13.4 128 | 129 | 130 | 131 | 132 | 133 | 134 | 135 | 136 | com.diffplug.spotless 137 | spotless-maven-plugin 138 | 139 | 140 | check 141 | none 142 | 143 | 144 | 145 | 146 | 147 | 148 | -------------------------------------------------------------------------------- /demo/library/src/main/java/eu/maveniverse/maven/mima/impl/library/Classpath.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.impl.library; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.Context; 13 | import eu.maveniverse.maven.mima.context.ContextOverrides; 14 | import eu.maveniverse.maven.mima.context.Runtime; 15 | import eu.maveniverse.maven.mima.context.Runtimes; 16 | import eu.maveniverse.maven.mima.extensions.mmr.MavenModelReader; 17 | import eu.maveniverse.maven.mima.extensions.mmr.ModelRequest; 18 | import eu.maveniverse.maven.mima.extensions.mmr.ModelResponse; 19 | import java.io.ByteArrayOutputStream; 20 | import java.io.IOException; 21 | import java.io.OutputStreamWriter; 22 | import java.io.Writer; 23 | import java.nio.charset.Charset; 24 | import org.apache.maven.model.Model; 25 | import org.apache.maven.model.io.xpp3.MavenXpp3Writer; 26 | import org.eclipse.aether.artifact.DefaultArtifact; 27 | import org.eclipse.aether.collection.CollectRequest; 28 | import org.eclipse.aether.graph.Dependency; 29 | import org.eclipse.aether.graph.DependencyNode; 30 | import org.eclipse.aether.impl.RemoteRepositoryManager; 31 | import org.eclipse.aether.repository.RemoteRepository; 32 | import org.eclipse.aether.repository.RepositoryPolicy; 33 | import org.eclipse.aether.resolution.ArtifactDescriptorException; 34 | import org.eclipse.aether.resolution.ArtifactResolutionException; 35 | import org.eclipse.aether.resolution.DependencyRequest; 36 | import org.eclipse.aether.resolution.DependencyResolutionException; 37 | import org.eclipse.aether.resolution.VersionResolutionException; 38 | import org.eclipse.aether.util.graph.visitor.PreorderNodeListGenerator; 39 | import org.slf4j.Logger; 40 | import org.slf4j.LoggerFactory; 41 | 42 | /** 43 | * This is an imaginary library class that wants to: 44 | *

48 | */ 49 | public class Classpath { 50 | 51 | private final Logger logger = LoggerFactory.getLogger(getClass()); 52 | 53 | public String model(ContextOverrides overrides, String artifactStr) 54 | throws VersionResolutionException, ArtifactResolutionException, ArtifactDescriptorException, IOException { 55 | requireNonNull(artifactStr); 56 | Runtime runtime = Runtimes.INSTANCE.getRuntime(); 57 | logger.debug("Runtimes.getRuntime: {}", runtime); 58 | 59 | try (Context context = runtime.create(overrides)) { 60 | MavenModelReader mmr = new MavenModelReader(context); 61 | ModelResponse response = mmr.readModel(ModelRequest.builder() 62 | .setArtifact(new DefaultArtifact(artifactStr)) 63 | .setRequestContext("classpath-demo") 64 | .build()); 65 | Model model = response.getEffectiveModel(); 66 | try (ByteArrayOutputStream outputStream = new ByteArrayOutputStream()) { 67 | String encoding = model.getModelEncoding(); 68 | if (encoding == null || encoding.length() <= 0) { 69 | encoding = "UTF-8"; 70 | } 71 | 72 | try (Writer out = new OutputStreamWriter(outputStream, Charset.forName(encoding))) { 73 | new MavenXpp3Writer().write(out, model); 74 | } 75 | return outputStream.toString(encoding); 76 | } 77 | } 78 | } 79 | 80 | public String classpath(ContextOverrides overrides, String artifactStr) throws DependencyResolutionException { 81 | requireNonNull(artifactStr); 82 | Runtime runtime = Runtimes.INSTANCE.getRuntime(); 83 | logger.debug("Runtimes.getRuntime: {}", runtime); 84 | 85 | // ad-hoc: create context w/ or w/o overrides 86 | // other way is to make this class manage context or manage context outside it 87 | // depends what you need: one shot or reuse of MIMA instance 88 | try (Context context = runtime.create(overrides)) { 89 | DefaultArtifact artifact = new DefaultArtifact(artifactStr); 90 | logger.info("doClasspath: {}", context.remoteRepositories()); 91 | 92 | RemoteRepositoryManager remoteRepositoryManager = context.lookup() 93 | .lookup(RemoteRepositoryManager.class) 94 | .orElseThrow(() -> new IllegalStateException("component not found")); 95 | for (RemoteRepository repository : context.remoteRepositories()) { 96 | RepositoryPolicy policy = remoteRepositoryManager.getPolicy( 97 | context.repositorySystemSession(), repository, !artifact.isSnapshot(), artifact.isSnapshot()); 98 | logger.info("Repository {} effective policy: {}", repository.getId(), policy); 99 | } 100 | 101 | Dependency dependency = new Dependency(artifact, "runtime"); 102 | CollectRequest collectRequest = new CollectRequest(); 103 | collectRequest.setRoot(dependency); 104 | collectRequest.setRepositories(context.remoteRepositories()); 105 | 106 | DependencyRequest dependencyRequest = new DependencyRequest(); 107 | dependencyRequest.setCollectRequest(collectRequest); 108 | 109 | DependencyNode rootNode = context.repositorySystem() 110 | .resolveDependencies(context.repositorySystemSession(), dependencyRequest) 111 | .getRoot(); 112 | 113 | PreorderNodeListGenerator nlg = new PreorderNodeListGenerator(); 114 | rootNode.accept(nlg); 115 | return nlg.getClassPath(); 116 | } 117 | } 118 | 119 | public static void main(String... args) { 120 | if (args.length != 1) { 121 | throw new IllegalArgumentException("g:a:v"); 122 | } 123 | Classpath classpath = new Classpath(); 124 | try { 125 | ContextOverrides overrides = 126 | ContextOverrides.create().withUserSettings(true).build(); 127 | 128 | String cp = classpath.classpath(overrides, args[0]); 129 | System.out.println("Classpath of " + args[0] + " is:"); 130 | System.out.println(cp); 131 | } catch (DependencyResolutionException e) { 132 | System.err.println("Error: " + e.getMessage()); 133 | } 134 | } 135 | } 136 | -------------------------------------------------------------------------------- /context/src/main/java/eu/maveniverse/maven/mima/context/Context.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.context; 9 | 10 | import static java.util.Objects.requireNonNull; 11 | 12 | import eu.maveniverse.maven.mima.context.internal.RuntimeSupport; 13 | import java.io.Closeable; 14 | import java.nio.file.Path; 15 | import java.util.List; 16 | import java.util.concurrent.atomic.AtomicBoolean; 17 | import org.eclipse.aether.RepositorySystem; 18 | import org.eclipse.aether.RepositorySystemSession; 19 | import org.eclipse.aether.repository.RemoteRepository; 20 | 21 | /** 22 | * The MIMA context holds references to {@link RepositorySystem}, {@link RepositorySystemSession} and list of 23 | * {@link RemoteRepository}. Context is {@link Closeable}, ideally used in try-with-resource constructs. 24 | *

25 | * The very first context instance application creates using {@link Runtime#create(ContextOverrides)} is called "root 26 | * context", and creation of it can be considered "heavy" operation (runtime dependent). Root context should be kept 27 | * open as long as application is expected to make use of Resolver. 28 | *

29 | * Context instances may be customized with {@link #customize(ContextOverrides)} method, in that case the returned 30 | * context is "derived" from this context. In those cases the context instances should be handled "as nested", so 31 | * closed in opposite order as they were obtained. Creating customized contexts can be considered "light" operation, 32 | * as they merely alter the {@link RepositorySystemSession} instance and repositories, while the 33 | * {@link RepositorySystem} is just inherited from this instance (is not reconstructed). 34 | * 35 | * @see Runtimes#getRuntime() 36 | * @see Runtime#create(ContextOverrides) 37 | */ 38 | public final class Context implements Closeable { 39 | private final AtomicBoolean closed; 40 | 41 | private final RuntimeSupport runtime; 42 | 43 | private final ContextOverrides contextOverrides; 44 | 45 | private final Path basedir; 46 | 47 | private final MavenUserHome mavenUserHome; 48 | 49 | private final MavenSystemHome mavenSystemHome; 50 | 51 | private final RepositorySystem repositorySystem; 52 | 53 | private final RepositorySystemSession repositorySystemSession; 54 | 55 | private final List remoteRepositories; 56 | 57 | private final HTTPProxy httpProxy; 58 | 59 | private final Lookup lookup; 60 | 61 | private final Runnable managedCloser; 62 | 63 | public Context( 64 | RuntimeSupport runtime, 65 | ContextOverrides contextOverrides, 66 | Path basedir, 67 | MavenUserHome mavenUserHome, 68 | MavenSystemHome mavenSystemHome, 69 | RepositorySystem repositorySystem, 70 | RepositorySystemSession repositorySystemSession, 71 | HTTPProxy httpProxy, 72 | Lookup lookup, 73 | Runnable managedCloser) { 74 | this.closed = new AtomicBoolean(false); 75 | this.runtime = requireNonNull(runtime); 76 | this.contextOverrides = requireNonNull(contextOverrides); 77 | this.basedir = requireNonNull(basedir); 78 | this.mavenUserHome = requireNonNull(mavenUserHome); 79 | this.mavenSystemHome = mavenSystemHome; 80 | this.repositorySystemSession = requireNonNull(repositorySystemSession); 81 | this.repositorySystem = requireNonNull(repositorySystem); 82 | this.remoteRepositories = contextOverrides.isKeepBareRepositories() 83 | ? contextOverrides.getRepositories() 84 | : repositorySystem.newResolutionRepositories( 85 | repositorySystemSession, contextOverrides.getRepositories()); 86 | this.httpProxy = httpProxy; 87 | this.lookup = requireNonNull(lookup); 88 | this.managedCloser = managedCloser; 89 | } 90 | 91 | /** 92 | * Returns the effective {@link ContextOverrides}, never {@code null}. This instance MAY be different from the user 93 | * supplied one to {@link Runtime#create(ContextOverrides)}, as it will contain discovered configuration as well. 94 | * 95 | * @since 2.1.0 96 | */ 97 | public ContextOverrides contextOverrides() { 98 | return contextOverrides; 99 | } 100 | 101 | /** 102 | * The basedir ("cwd"), never {@code null}. 103 | * 104 | * @since 2.3.0 105 | */ 106 | public Path basedir() { 107 | return basedir; 108 | } 109 | 110 | /** 111 | * Returns effective {@link MavenUserHome}, never {@code null}. 112 | * 113 | * @since 2.1.0 114 | */ 115 | public MavenUserHome mavenUserHome() { 116 | return mavenUserHome; 117 | } 118 | 119 | /** 120 | * Returns effective {@link MavenSystemHome}, may be {@code null}, if no Maven Home discovered. 121 | * 122 | * @since 2.1.0 123 | */ 124 | public MavenSystemHome mavenSystemHome() { 125 | return mavenSystemHome; 126 | } 127 | 128 | /** 129 | * Returns the {@link RepositorySystemSession}, never {@code null}. 130 | */ 131 | public RepositorySystemSession repositorySystemSession() { 132 | return repositorySystemSession; 133 | } 134 | 135 | /** 136 | * Returns the {@link RepositorySystem}, never {@code null}. 137 | */ 138 | public RepositorySystem repositorySystem() { 139 | return repositorySystem; 140 | } 141 | 142 | /** 143 | * Returns the list of {@link RemoteRepository}, never {@code null}. 144 | */ 145 | public List remoteRepositories() { 146 | return remoteRepositories; 147 | } 148 | 149 | /** 150 | * Returns HTTP Proxy that Resolver will use, or {@code null}. This configuration may come from user 151 | * {@code settings.xml}. 152 | * 153 | * @since 2.4.0 154 | */ 155 | public HTTPProxy httpProxy() { 156 | return httpProxy; 157 | } 158 | 159 | /** 160 | * Returns {@link Lookup} instance usable to look up resolver components, never {@code null}. 161 | * 162 | * @since 2.4.10 163 | */ 164 | public Lookup lookup() { 165 | return lookup; 166 | } 167 | 168 | /** 169 | * Returns a new {@link Context} instance, that is customized using passed in {@link ContextOverrides}, using this 170 | * instance as "base". 171 | */ 172 | public Context customize(ContextOverrides overrides) { 173 | if (closed.get()) { 174 | throw new IllegalStateException("context is closed"); 175 | } 176 | return runtime.customizeContext(overrides, this, false); 177 | } 178 | 179 | /** 180 | * Exposes {@link Runtime} instance used to create this context instance. 181 | */ 182 | public Runtime getRuntime() { 183 | return runtime; 184 | } 185 | 186 | /** 187 | * Closes the context. Once closed context instance should not be used anymore. 188 | */ 189 | @Override 190 | public void close() { 191 | if (closed.compareAndSet(false, true)) { 192 | // in the future session may become closeable as well 193 | // repositorySystemSession.close(); 194 | if (managedCloser != null) { 195 | managedCloser.run(); 196 | } 197 | } 198 | } 199 | } 200 | -------------------------------------------------------------------------------- /mvnw.cmd: -------------------------------------------------------------------------------- 1 | <# : batch portion 2 | @REM ---------------------------------------------------------------------------- 3 | @REM Licensed to the Apache Software Foundation (ASF) under one 4 | @REM or more contributor license agreements. See the NOTICE file 5 | @REM distributed with this work for additional information 6 | @REM regarding copyright ownership. The ASF licenses this file 7 | @REM to you under the Apache License, Version 2.0 (the 8 | @REM "License"); you may not use this file except in compliance 9 | @REM with the License. You may obtain a copy of the License at 10 | @REM 11 | @REM http://www.apache.org/licenses/LICENSE-2.0 12 | @REM 13 | @REM Unless required by applicable law or agreed to in writing, 14 | @REM software distributed under the License is distributed on an 15 | @REM "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY 16 | @REM KIND, either express or implied. See the License for the 17 | @REM specific language governing permissions and limitations 18 | @REM under the License. 19 | @REM ---------------------------------------------------------------------------- 20 | 21 | @REM ---------------------------------------------------------------------------- 22 | @REM Apache Maven Wrapper startup batch script, version 3.3.4 23 | @REM 24 | @REM Optional ENV vars 25 | @REM MVNW_REPOURL - repo url base for downloading maven distribution 26 | @REM MVNW_USERNAME/MVNW_PASSWORD - user and password for downloading maven 27 | @REM MVNW_VERBOSE - true: enable verbose log; others: silence the output 28 | @REM ---------------------------------------------------------------------------- 29 | 30 | @IF "%__MVNW_ARG0_NAME__%"=="" (SET __MVNW_ARG0_NAME__=%~nx0) 31 | @SET __MVNW_CMD__= 32 | @SET __MVNW_ERROR__= 33 | @SET __MVNW_PSMODULEP_SAVE=%PSModulePath% 34 | @SET PSModulePath= 35 | @FOR /F "usebackq tokens=1* delims==" %%A IN (`powershell -noprofile "& {$scriptDir='%~dp0'; $script='%__MVNW_ARG0_NAME__%'; icm -ScriptBlock ([Scriptblock]::Create((Get-Content -Raw '%~f0'))) -NoNewScope}"`) DO @( 36 | IF "%%A"=="MVN_CMD" (set __MVNW_CMD__=%%B) ELSE IF "%%B"=="" (echo %%A) ELSE (echo %%A=%%B) 37 | ) 38 | @SET PSModulePath=%__MVNW_PSMODULEP_SAVE% 39 | @SET __MVNW_PSMODULEP_SAVE= 40 | @SET __MVNW_ARG0_NAME__= 41 | @SET MVNW_USERNAME= 42 | @SET MVNW_PASSWORD= 43 | @IF NOT "%__MVNW_CMD__%"=="" ("%__MVNW_CMD__%" %*) 44 | @echo Cannot start maven from wrapper >&2 && exit /b 1 45 | @GOTO :EOF 46 | : end batch / begin powershell #> 47 | 48 | $ErrorActionPreference = "Stop" 49 | if ($env:MVNW_VERBOSE -eq "true") { 50 | $VerbosePreference = "Continue" 51 | } 52 | 53 | # calculate distributionUrl, requires .mvn/wrapper/maven-wrapper.properties 54 | $distributionUrl = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionUrl 55 | if (!$distributionUrl) { 56 | Write-Error "cannot read distributionUrl property in $scriptDir/.mvn/wrapper/maven-wrapper.properties" 57 | } 58 | 59 | switch -wildcard -casesensitive ( $($distributionUrl -replace '^.*/','') ) { 60 | "maven-mvnd-*" { 61 | $USE_MVND = $true 62 | $distributionUrl = $distributionUrl -replace '-bin\.[^.]*$',"-windows-amd64.zip" 63 | $MVN_CMD = "mvnd.cmd" 64 | break 65 | } 66 | default { 67 | $USE_MVND = $false 68 | $MVN_CMD = $script -replace '^mvnw','mvn' 69 | break 70 | } 71 | } 72 | 73 | # apply MVNW_REPOURL and calculate MAVEN_HOME 74 | # maven home pattern: ~/.m2/wrapper/dists/{apache-maven-,maven-mvnd--}/ 75 | if ($env:MVNW_REPOURL) { 76 | $MVNW_REPO_PATTERN = if ($USE_MVND -eq $False) { "/org/apache/maven/" } else { "/maven/mvnd/" } 77 | $distributionUrl = "$env:MVNW_REPOURL$MVNW_REPO_PATTERN$($distributionUrl -replace "^.*$MVNW_REPO_PATTERN",'')" 78 | } 79 | $distributionUrlName = $distributionUrl -replace '^.*/','' 80 | $distributionUrlNameMain = $distributionUrlName -replace '\.[^.]*$','' -replace '-bin$','' 81 | 82 | $MAVEN_M2_PATH = "$HOME/.m2" 83 | if ($env:MAVEN_USER_HOME) { 84 | $MAVEN_M2_PATH = "$env:MAVEN_USER_HOME" 85 | } 86 | 87 | if (-not (Test-Path -Path $MAVEN_M2_PATH)) { 88 | New-Item -Path $MAVEN_M2_PATH -ItemType Directory | Out-Null 89 | } 90 | 91 | $MAVEN_WRAPPER_DISTS = $null 92 | if ((Get-Item $MAVEN_M2_PATH).Target[0] -eq $null) { 93 | $MAVEN_WRAPPER_DISTS = "$MAVEN_M2_PATH/wrapper/dists" 94 | } else { 95 | $MAVEN_WRAPPER_DISTS = (Get-Item $MAVEN_M2_PATH).Target[0] + "/wrapper/dists" 96 | } 97 | 98 | $MAVEN_HOME_PARENT = "$MAVEN_WRAPPER_DISTS/$distributionUrlNameMain" 99 | $MAVEN_HOME_NAME = ([System.Security.Cryptography.SHA256]::Create().ComputeHash([byte[]][char[]]$distributionUrl) | ForEach-Object {$_.ToString("x2")}) -join '' 100 | $MAVEN_HOME = "$MAVEN_HOME_PARENT/$MAVEN_HOME_NAME" 101 | 102 | if (Test-Path -Path "$MAVEN_HOME" -PathType Container) { 103 | Write-Verbose "found existing MAVEN_HOME at $MAVEN_HOME" 104 | Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" 105 | exit $? 106 | } 107 | 108 | if (! $distributionUrlNameMain -or ($distributionUrlName -eq $distributionUrlNameMain)) { 109 | Write-Error "distributionUrl is not valid, must end with *-bin.zip, but found $distributionUrl" 110 | } 111 | 112 | # prepare tmp dir 113 | $TMP_DOWNLOAD_DIR_HOLDER = New-TemporaryFile 114 | $TMP_DOWNLOAD_DIR = New-Item -Itemtype Directory -Path "$TMP_DOWNLOAD_DIR_HOLDER.dir" 115 | $TMP_DOWNLOAD_DIR_HOLDER.Delete() | Out-Null 116 | trap { 117 | if ($TMP_DOWNLOAD_DIR.Exists) { 118 | try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } 119 | catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } 120 | } 121 | } 122 | 123 | New-Item -Itemtype Directory -Path "$MAVEN_HOME_PARENT" -Force | Out-Null 124 | 125 | # Download and Install Apache Maven 126 | Write-Verbose "Couldn't find MAVEN_HOME, downloading and installing it ..." 127 | Write-Verbose "Downloading from: $distributionUrl" 128 | Write-Verbose "Downloading to: $TMP_DOWNLOAD_DIR/$distributionUrlName" 129 | 130 | $webclient = New-Object System.Net.WebClient 131 | if ($env:MVNW_USERNAME -and $env:MVNW_PASSWORD) { 132 | $webclient.Credentials = New-Object System.Net.NetworkCredential($env:MVNW_USERNAME, $env:MVNW_PASSWORD) 133 | } 134 | [Net.ServicePointManager]::SecurityProtocol = [Net.SecurityProtocolType]::Tls12 135 | $webclient.DownloadFile($distributionUrl, "$TMP_DOWNLOAD_DIR/$distributionUrlName") | Out-Null 136 | 137 | # If specified, validate the SHA-256 sum of the Maven distribution zip file 138 | $distributionSha256Sum = (Get-Content -Raw "$scriptDir/.mvn/wrapper/maven-wrapper.properties" | ConvertFrom-StringData).distributionSha256Sum 139 | if ($distributionSha256Sum) { 140 | if ($USE_MVND) { 141 | Write-Error "Checksum validation is not supported for maven-mvnd. `nPlease disable validation by removing 'distributionSha256Sum' from your maven-wrapper.properties." 142 | } 143 | Import-Module $PSHOME\Modules\Microsoft.PowerShell.Utility -Function Get-FileHash 144 | if ((Get-FileHash "$TMP_DOWNLOAD_DIR/$distributionUrlName" -Algorithm SHA256).Hash.ToLower() -ne $distributionSha256Sum) { 145 | Write-Error "Error: Failed to validate Maven distribution SHA-256, your Maven distribution might be compromised. If you updated your Maven version, you need to update the specified distributionSha256Sum property." 146 | } 147 | } 148 | 149 | # unzip and move 150 | Expand-Archive "$TMP_DOWNLOAD_DIR/$distributionUrlName" -DestinationPath "$TMP_DOWNLOAD_DIR" | Out-Null 151 | 152 | # Find the actual extracted directory name (handles snapshots where filename != directory name) 153 | $actualDistributionDir = "" 154 | 155 | # First try the expected directory name (for regular distributions) 156 | $expectedPath = Join-Path "$TMP_DOWNLOAD_DIR" "$distributionUrlNameMain" 157 | $expectedMvnPath = Join-Path "$expectedPath" "bin/$MVN_CMD" 158 | if ((Test-Path -Path $expectedPath -PathType Container) -and (Test-Path -Path $expectedMvnPath -PathType Leaf)) { 159 | $actualDistributionDir = $distributionUrlNameMain 160 | } 161 | 162 | # If not found, search for any directory with the Maven executable (for snapshots) 163 | if (!$actualDistributionDir) { 164 | Get-ChildItem -Path "$TMP_DOWNLOAD_DIR" -Directory | ForEach-Object { 165 | $testPath = Join-Path $_.FullName "bin/$MVN_CMD" 166 | if (Test-Path -Path $testPath -PathType Leaf) { 167 | $actualDistributionDir = $_.Name 168 | } 169 | } 170 | } 171 | 172 | if (!$actualDistributionDir) { 173 | Write-Error "Could not find Maven distribution directory in extracted archive" 174 | } 175 | 176 | Write-Verbose "Found extracted Maven distribution directory: $actualDistributionDir" 177 | Rename-Item -Path "$TMP_DOWNLOAD_DIR/$actualDistributionDir" -NewName $MAVEN_HOME_NAME | Out-Null 178 | try { 179 | Move-Item -Path "$TMP_DOWNLOAD_DIR/$MAVEN_HOME_NAME" -Destination $MAVEN_HOME_PARENT | Out-Null 180 | } catch { 181 | if (! (Test-Path -Path "$MAVEN_HOME" -PathType Container)) { 182 | Write-Error "fail to move MAVEN_HOME" 183 | } 184 | } finally { 185 | try { Remove-Item $TMP_DOWNLOAD_DIR -Recurse -Force | Out-Null } 186 | catch { Write-Warning "Cannot remove $TMP_DOWNLOAD_DIR" } 187 | } 188 | 189 | Write-Output "MVN_CMD=$MAVEN_HOME/bin/$MVN_CMD" 190 | -------------------------------------------------------------------------------- /runtime/embedded-maven/src/main/java/eu/maveniverse/maven/mima/runtime/maven/MavenRuntime.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.runtime.maven; 9 | 10 | import eu.maveniverse.maven.mima.context.Context; 11 | import eu.maveniverse.maven.mima.context.ContextOverrides; 12 | import eu.maveniverse.maven.mima.context.HTTPProxy; 13 | import eu.maveniverse.maven.mima.context.MavenSystemHome; 14 | import eu.maveniverse.maven.mima.context.MavenUserHome; 15 | import eu.maveniverse.maven.mima.context.internal.MavenSystemHomeImpl; 16 | import eu.maveniverse.maven.mima.context.internal.MavenUserHomeImpl; 17 | import eu.maveniverse.maven.mima.context.internal.RuntimeSupport; 18 | import eu.maveniverse.maven.mima.runtime.maven.internal.PlexusLookup; 19 | import java.nio.file.Path; 20 | import java.nio.file.Paths; 21 | import java.util.ArrayList; 22 | import java.util.Collection; 23 | import java.util.HashMap; 24 | import java.util.List; 25 | import java.util.stream.Collectors; 26 | import javax.inject.Inject; 27 | import javax.inject.Named; 28 | import javax.inject.Provider; 29 | import javax.inject.Singleton; 30 | import org.apache.maven.execution.MavenExecutionRequest; 31 | import org.apache.maven.execution.MavenSession; 32 | import org.apache.maven.rtinfo.RuntimeInformation; 33 | import org.apache.maven.settings.Proxy; 34 | import org.codehaus.plexus.PlexusContainer; 35 | import org.eclipse.aether.RepositorySystem; 36 | import org.eclipse.aether.RepositorySystemSession; 37 | import org.eclipse.aether.repository.RemoteRepository; 38 | import org.eclipse.sisu.Nullable; 39 | 40 | @Singleton 41 | @Named 42 | public final class MavenRuntime extends RuntimeSupport { 43 | private final RepositorySystem repositorySystem; 44 | 45 | private final PlexusContainer plexusContainer; 46 | 47 | private final Provider mavenSessionProvider; 48 | 49 | private final RuntimeInformation runtimeInformation; 50 | 51 | @Inject 52 | public MavenRuntime( 53 | @Nullable RepositorySystem repositorySystem, 54 | @Nullable PlexusContainer plexusContainer, 55 | Provider mavenSessionProvider, 56 | @Nullable RuntimeInformation rt) { 57 | super( 58 | "embedded-maven", 59 | discoverArtifactVersion( 60 | MavenRuntime.class, "eu.maveniverse.maven.mima.runtime", "embedded-maven", UNKNOWN_VERSION), 61 | 10, 62 | mavenVersion(rt), 63 | "embedded"); 64 | // when embedded in Maven, classloading isolation does not allow us to discover Resolver version 65 | this.repositorySystem = repositorySystem; 66 | this.plexusContainer = plexusContainer; 67 | this.mavenSessionProvider = mavenSessionProvider; 68 | this.runtimeInformation = rt; 69 | } 70 | 71 | public boolean isReady() { 72 | return repositorySystem != null && plexusContainer != null && runtimeInformation != null; 73 | } 74 | 75 | private static String mavenVersion(RuntimeInformation runtimeInformation) { 76 | if (runtimeInformation != null) { 77 | String mavenVersion = runtimeInformation.getMavenVersion(); 78 | if (mavenVersion != null && !mavenVersion.trim().isEmpty()) { 79 | return mavenVersion; 80 | } 81 | } 82 | return UNKNOWN_VERSION; 83 | } 84 | 85 | @Override 86 | public boolean managedRepositorySystem() { 87 | return false; 88 | } 89 | 90 | @Override 91 | public Context create(ContextOverrides overrides) { 92 | MavenSession mavenSession = mavenSessionProvider.get(); 93 | boolean projectPresent = mavenSession.getRequest().isProjectPresent(); 94 | 95 | Path basedir; 96 | if (projectPresent) { 97 | basedir = mavenSession.getCurrentProject().getBasedir().toPath().toAbsolutePath(); 98 | } else { 99 | basedir = DEFAULT_BASEDIR; 100 | } 101 | 102 | List repositories = 103 | new ArrayList<>(mavenSession.getCurrentProject().getRemoteProjectRepositories()); 104 | if (overrides.getRepositories() != ContextOverrides.DEFAULT_REMOTE_REPOSITORIES) { 105 | List overrideRepositories = repositorySystem.newResolutionRepositories( 106 | mavenSession.getRepositorySession(), overrides.getRepositories()); 107 | switch (overrides.addRepositoriesOp()) { 108 | case REPLACE: 109 | repositories.clear(); 110 | repositories.addAll(overrideRepositories); 111 | break; 112 | case PREPEND: 113 | repositories.addAll(0, overrideRepositories); 114 | break; 115 | case APPEND: 116 | repositories.addAll(overrideRepositories); 117 | break; 118 | default: 119 | throw new IllegalStateException("Unknown overrides op: " + overrides.addRepositoriesOp()); 120 | } 121 | } 122 | 123 | MavenUserHome mavenUserHome = discoverMavenUserHome(mavenSession.getRequest()); 124 | MavenSystemHome mavenSystemHome = discoverMavenSystemHome(mavenSession.getRequest()); 125 | RepositorySystemSession session = mavenSession.getRepositorySession(); 126 | 127 | ContextOverrides.Builder effectiveOverridesBuilder = overrides.toBuilder(); 128 | effectiveOverridesBuilder.keepBareRepositories(true); // embedded; maven handles them 129 | effectiveOverridesBuilder.withUserSettings(true); // embedded 130 | effectiveOverridesBuilder.repositories(repositories); 131 | effectiveOverridesBuilder.systemProperties(session.getSystemProperties()); 132 | effectiveOverridesBuilder.userProperties(session.getUserProperties()); 133 | effectiveOverridesBuilder.configProperties(session.getConfigProperties()); 134 | effectiveOverridesBuilder.withActiveProfileIds( 135 | mavenSession.getCurrentProject().getInjectedProfileIds().values().stream() 136 | .flatMap(Collection::stream) 137 | .collect(Collectors.toList())); 138 | effectiveOverridesBuilder.withInactiveProfileIds( 139 | mavenSession.getRequest().getInactiveProfiles()); 140 | 141 | ContextOverrides effective = effectiveOverridesBuilder.build(); 142 | return customizeContext( 143 | this, 144 | effective, 145 | new Context( 146 | this, 147 | effective, 148 | basedir, 149 | mavenUserHome, 150 | mavenSystemHome, 151 | repositorySystem, 152 | session, 153 | toHTTPProxy(mavenSession.getSettings().getActiveProxy()), 154 | new PlexusLookup(plexusContainer), 155 | null), 156 | false); // unmanaged context: close should NOT shut down repositorySystem 157 | } 158 | 159 | private HTTPProxy toHTTPProxy(Proxy proxy) { 160 | if (proxy == null) { 161 | return null; 162 | } 163 | 164 | HashMap data = new HashMap<>(); 165 | if (proxy.getUsername() != null) { 166 | data.put("username", proxy.getUsername()); 167 | } 168 | if (proxy.getPassword() != null) { 169 | data.put("password", proxy.getPassword()); 170 | } 171 | return new HTTPProxy(proxy.getProtocol(), proxy.getHost(), proxy.getPort(), proxy.getNonProxyHosts(), data); 172 | } 173 | 174 | private MavenUserHome discoverMavenUserHome(MavenExecutionRequest executionRequest) { 175 | return new MavenUserHomeImpl( 176 | DEFAULT_MAVEN_USER_HOME, 177 | executionRequest.getUserSettingsFile() != null 178 | ? executionRequest.getUserSettingsFile().toPath().toAbsolutePath() 179 | : null, 180 | null, 181 | executionRequest.getUserToolchainsFile() != null 182 | ? executionRequest.getUserToolchainsFile().toPath().toAbsolutePath() 183 | : null, 184 | executionRequest.getLocalRepositoryPath().toPath().toAbsolutePath()); 185 | } 186 | 187 | private MavenSystemHome discoverMavenSystemHome(MavenExecutionRequest executionRequest) { 188 | return new MavenSystemHomeImpl( 189 | Paths.get(System.getProperty("maven.home")).toAbsolutePath(), 190 | executionRequest.getGlobalSettingsFile() != null 191 | ? executionRequest.getGlobalSettingsFile().toPath().toAbsolutePath() 192 | : null, 193 | executionRequest.getGlobalToolchainsFile() != null 194 | ? executionRequest.getGlobalToolchainsFile().toPath().toAbsolutePath() 195 | : null); 196 | } 197 | } 198 | -------------------------------------------------------------------------------- /extensions/mmr/src/main/java/eu/maveniverse/maven/mima/extensions/mmr/internal/ModelResolverImpl.java: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2023-2024 Maveniverse Org. 3 | * All rights reserved. This program and the accompanying materials 4 | * are made available under the terms of the Eclipse Public License v2.0 5 | * which accompanies this distribution, and is available at 6 | * https://www.eclipse.org/legal/epl-v20.html 7 | */ 8 | package eu.maveniverse.maven.mima.extensions.mmr.internal; 9 | 10 | import java.io.File; 11 | import java.util.ArrayList; 12 | import java.util.Collections; 13 | import java.util.HashSet; 14 | import java.util.Iterator; 15 | import java.util.List; 16 | import java.util.Set; 17 | import org.apache.maven.model.Dependency; 18 | import org.apache.maven.model.Parent; 19 | import org.apache.maven.model.Repository; 20 | import org.apache.maven.model.building.FileModelSource; 21 | import org.apache.maven.model.building.ModelSource; 22 | import org.apache.maven.model.resolution.InvalidRepositoryException; 23 | import org.apache.maven.model.resolution.ModelResolver; 24 | import org.apache.maven.model.resolution.UnresolvableModelException; 25 | import org.apache.maven.repository.internal.ArtifactDescriptorUtils; 26 | import org.apache.maven.repository.internal.DefaultArtifactDescriptorReader; 27 | import org.eclipse.aether.RepositorySystem; 28 | import org.eclipse.aether.RepositorySystemSession; 29 | import org.eclipse.aether.RequestTrace; 30 | import org.eclipse.aether.artifact.Artifact; 31 | import org.eclipse.aether.artifact.DefaultArtifact; 32 | import org.eclipse.aether.impl.RemoteRepositoryManager; 33 | import org.eclipse.aether.repository.RemoteRepository; 34 | import org.eclipse.aether.resolution.ArtifactRequest; 35 | import org.eclipse.aether.resolution.ArtifactResolutionException; 36 | import org.eclipse.aether.resolution.VersionRangeRequest; 37 | import org.eclipse.aether.resolution.VersionRangeResolutionException; 38 | import org.eclipse.aether.resolution.VersionRangeResult; 39 | 40 | /** 41 | * A model resolver to assist building of dependency POMs. This resolver gives priority to those repositories that have 42 | * been initially specified and repositories discovered in dependency POMs are recessive merged into the search chain. 43 | * 44 | * @author Benjamin Bentmann 45 | * @see DefaultArtifactDescriptorReader 46 | */ 47 | public class ModelResolverImpl implements ModelResolver { 48 | private final RepositorySystem repositorySystem; 49 | 50 | private final RepositorySystemSession session; 51 | 52 | private final RequestTrace trace; 53 | 54 | private final String context; 55 | 56 | private List repositories; 57 | 58 | private final List externalRepositories; 59 | 60 | private final RemoteRepositoryManager remoteRepositoryManager; 61 | 62 | private final Set repositoryIds; 63 | 64 | public ModelResolverImpl( 65 | RepositorySystem repositorySystem, 66 | RepositorySystemSession session, 67 | RequestTrace trace, 68 | String context, 69 | RemoteRepositoryManager remoteRepositoryManager, 70 | List repositories) { 71 | this.repositorySystem = repositorySystem; 72 | this.session = session; 73 | this.trace = trace; 74 | this.context = context; 75 | this.remoteRepositoryManager = remoteRepositoryManager; 76 | this.repositories = repositories; 77 | this.externalRepositories = Collections.unmodifiableList(new ArrayList<>(repositories)); 78 | 79 | this.repositoryIds = new HashSet<>(); 80 | } 81 | 82 | private ModelResolverImpl(ModelResolverImpl original) { 83 | this.repositorySystem = original.repositorySystem; 84 | this.session = original.session; 85 | this.trace = original.trace; 86 | this.context = original.context; 87 | this.remoteRepositoryManager = original.remoteRepositoryManager; 88 | this.repositories = new ArrayList<>(original.repositories); 89 | this.externalRepositories = original.externalRepositories; 90 | this.repositoryIds = new HashSet<>(original.repositoryIds); 91 | } 92 | 93 | @Override 94 | public void addRepository(Repository repository) throws InvalidRepositoryException { 95 | addRepository(repository, false); 96 | } 97 | 98 | @Override 99 | public void addRepository(final Repository repository, boolean replace) throws InvalidRepositoryException { 100 | if (session.isIgnoreArtifactDescriptorRepositories()) { 101 | return; 102 | } 103 | 104 | if (!repositoryIds.add(repository.getId())) { 105 | if (!replace) { 106 | return; 107 | } 108 | 109 | removeMatchingRepository(repositories, repository.getId()); 110 | } 111 | 112 | List newRepositories = 113 | Collections.singletonList(ArtifactDescriptorUtils.toRemoteRepository(repository)); 114 | 115 | this.repositories = remoteRepositoryManager.aggregateRepositories(session, repositories, newRepositories, true); 116 | } 117 | 118 | private static void removeMatchingRepository(Iterable repositories, final String id) { 119 | Iterator iterator = repositories.iterator(); 120 | while (iterator.hasNext()) { 121 | RemoteRepository remoteRepository = iterator.next(); 122 | if (remoteRepository.getId().equals(id)) { 123 | iterator.remove(); 124 | } 125 | } 126 | } 127 | 128 | @Override 129 | public ModelResolver newCopy() { 130 | return new ModelResolverImpl(this); 131 | } 132 | 133 | @Override 134 | public ModelSource resolveModel(String groupId, String artifactId, String version) 135 | throws UnresolvableModelException { 136 | Artifact pomArtifact = new DefaultArtifact(groupId, artifactId, "", "pom", version); 137 | 138 | try { 139 | ArtifactRequest request = new ArtifactRequest(pomArtifact, repositories, context); 140 | request.setTrace(trace); 141 | pomArtifact = repositorySystem.resolveArtifact(session, request).getArtifact(); 142 | } catch (ArtifactResolutionException e) { 143 | throw new UnresolvableModelException(e.getMessage(), groupId, artifactId, version, e); 144 | } 145 | 146 | File pomFile = pomArtifact.getFile(); 147 | 148 | return new FileModelSource(pomFile); 149 | } 150 | 151 | @Override 152 | public ModelSource resolveModel(final Parent parent) throws UnresolvableModelException { 153 | try { 154 | final Artifact artifact = 155 | new DefaultArtifact(parent.getGroupId(), parent.getArtifactId(), "", "pom", parent.getVersion()); 156 | 157 | final VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, repositories, context); 158 | versionRangeRequest.setTrace(trace); 159 | 160 | final VersionRangeResult versionRangeResult = 161 | repositorySystem.resolveVersionRange(session, versionRangeRequest); 162 | 163 | if (versionRangeResult.getHighestVersion() == null) { 164 | throw new UnresolvableModelException( 165 | String.format( 166 | "No versions matched the requested parent version range '%s'", parent.getVersion()), 167 | parent.getGroupId(), 168 | parent.getArtifactId(), 169 | parent.getVersion()); 170 | } 171 | 172 | if (versionRangeResult.getVersionConstraint() != null 173 | && versionRangeResult.getVersionConstraint().getRange() != null 174 | && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null) { 175 | // Message below is checked for in the MNG-2199 core IT. 176 | throw new UnresolvableModelException( 177 | String.format( 178 | "The requested parent version range '%s' does not specify an upper bound", 179 | parent.getVersion()), 180 | parent.getGroupId(), 181 | parent.getArtifactId(), 182 | parent.getVersion()); 183 | } 184 | 185 | parent.setVersion(versionRangeResult.getHighestVersion().toString()); 186 | 187 | return resolveModel(parent.getGroupId(), parent.getArtifactId(), parent.getVersion()); 188 | } catch (final VersionRangeResolutionException e) { 189 | throw new UnresolvableModelException( 190 | e.getMessage(), parent.getGroupId(), parent.getArtifactId(), parent.getVersion(), e); 191 | } 192 | } 193 | 194 | @Override 195 | public ModelSource resolveModel(final Dependency dependency) throws UnresolvableModelException { 196 | try { 197 | final Artifact artifact = new DefaultArtifact( 198 | dependency.getGroupId(), dependency.getArtifactId(), "", "pom", dependency.getVersion()); 199 | 200 | final VersionRangeRequest versionRangeRequest = new VersionRangeRequest(artifact, repositories, context); 201 | versionRangeRequest.setTrace(trace); 202 | 203 | final VersionRangeResult versionRangeResult = 204 | repositorySystem.resolveVersionRange(session, versionRangeRequest); 205 | 206 | if (versionRangeResult.getHighestVersion() == null) { 207 | throw new UnresolvableModelException( 208 | String.format( 209 | "No versions matched the requested dependency version range '%s'", 210 | dependency.getVersion()), 211 | dependency.getGroupId(), 212 | dependency.getArtifactId(), 213 | dependency.getVersion()); 214 | } 215 | 216 | if (versionRangeResult.getVersionConstraint() != null 217 | && versionRangeResult.getVersionConstraint().getRange() != null 218 | && versionRangeResult.getVersionConstraint().getRange().getUpperBound() == null) { 219 | // Message below is checked for in the MNG-4463 core IT. 220 | throw new UnresolvableModelException( 221 | String.format( 222 | "The requested dependency version range '%s' does not specify an upper bound", 223 | dependency.getVersion()), 224 | dependency.getGroupId(), 225 | dependency.getArtifactId(), 226 | dependency.getVersion()); 227 | } 228 | 229 | dependency.setVersion(versionRangeResult.getHighestVersion().toString()); 230 | 231 | return resolveModel(dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion()); 232 | } catch (VersionRangeResolutionException e) { 233 | throw new UnresolvableModelException( 234 | e.getMessage(), dependency.getGroupId(), dependency.getArtifactId(), dependency.getVersion(), e); 235 | } 236 | } 237 | } 238 | --------------------------------------------------------------------------------