From 6474beedec3c7e8aacdef8f0e7712e90cdc43973 Mon Sep 17 00:00:00 2001 From: Alexey Loubyansky Date: Wed, 6 Nov 2019 18:40:32 +0100 Subject: [PATCH] Make the create project mojo resolve the latest version of the universe by default and fall back to the bundled quarkus-bom in offline mode --- .../io/quarkus/maven/BuildFileMojoBase.java | 31 +- .../io/quarkus/maven/CreateProjectMojo.java | 32 +- .../java/io/quarkus/maven/CreateUtils.java | 54 +++ .../resolver/ResolverSetupCleanup.java | 12 +- .../bootstrap/resolver/TsArtifact.java | 2 +- .../bootstrap/resolver/TsRepoBuilder.java | 6 +- .../io/quarkus/platform/tools/ToolsUtils.java | 4 + .../platform-descriptor-resolver-json/pom.xml | 8 +- .../PlatformDescriptorLoadingException.java | 16 + ...QuarkusJsonPlatformDescriptorResolver.java | 309 +++++++++++++----- .../json/VersionNotAvailableException.java | 14 + .../json/demo/JsonDescriptorResolverDemo.java | 10 +- ...kusJsonPlatformDescriptorResolverTest.java | 171 ++++++++++ .../TestJsonPlatformDescriptorLoader.java | 94 ++++++ .../TestPlatformJsonDescriptorProvider.java | 53 +++ ...r.json.QuarkusJsonPlatformDescriptorLoader | 1 + .../maven/it/KotlinCreateMavenProjectIT.java | 4 + .../invoker.properties | 2 +- .../it/setup-on-min-pom-it/invoker.properties | 2 +- .../invoker.properties | 2 +- .../io/quarkus/maven/it/AddExtensionIT.java | 3 + .../quarkus/maven/it/CreateProjectMojoIT.java | 6 + .../maven/it/ScalaCreateMavenProjectIT.java | 4 + 23 files changed, 703 insertions(+), 137 deletions(-) create mode 100644 independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/PlatformDescriptorLoadingException.java create mode 100644 independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/VersionNotAvailableException.java create mode 100644 independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/QuarkusJsonPlatformDescriptorResolverTest.java create mode 100644 independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java create mode 100644 independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestPlatformJsonDescriptorProvider.java create mode 100644 independent-projects/tools/platform-descriptor-resolver-json/src/test/resources/META-INF/services/io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoader diff --git a/devtools/maven/src/main/java/io/quarkus/maven/BuildFileMojoBase.java b/devtools/maven/src/main/java/io/quarkus/maven/BuildFileMojoBase.java index 215328689dccc..c985e767a5b8e 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/BuildFileMojoBase.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/BuildFileMojoBase.java @@ -25,6 +25,7 @@ import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver; import io.quarkus.platform.tools.MessageWriter; +import io.quarkus.platform.tools.ToolsConstants; import io.quarkus.platform.tools.config.QuarkusPlatformConfig; import io.quarkus.platform.tools.maven.MojoMessageWriter; @@ -42,10 +43,10 @@ public abstract class BuildFileMojoBase extends AbstractMojo { @Parameter(defaultValue = "${project.remoteProjectRepositories}", readonly = true, required = true) protected List repos; - @Parameter(property = "bomGroupId", defaultValue = CreateUtils.DEFAULT_PLATFORM_BOM_GROUP_ID) + @Parameter(property = "bomGroupId", defaultValue = ToolsConstants.DEFAULT_PLATFORM_BOM_GROUP_ID) private String bomGroupId; - @Parameter(property = "bomArtifactId", defaultValue = CreateUtils.DEFAULT_PLATFORM_BOM_ARTIFACT_ID) + @Parameter(property = "bomArtifactId", required = false) private String bomArtifactId; @Parameter(property = "bomVersion", required = false) @@ -128,34 +129,10 @@ public void execute() throws MojoExecutionException { || new File(project.getBasedir(), "build.gradle.kts").exists()) { // Gradle project buildFile = new GradleBuildFile(new FileProjectWriter(project.getBasedir())); - } else { - } if (!QuarkusPlatformConfig.hasGlobalDefault()) { - String bomGroupId = this.bomGroupId; - if (bomGroupId == null) { - bomGroupId = CreateUtils.DEFAULT_PLATFORM_BOM_GROUP_ID; - } - String bomArtifactId = this.bomArtifactId; - if (bomArtifactId == null) { - bomArtifactId = CreateUtils.DEFAULT_PLATFORM_BOM_ARTIFACT_ID; - } - - String bomVersion = this.bomVersion; - if (bomVersion == null) { - // if the BOM artifactId matches Quarkus BOM we use the plugins version as its version - bomVersion = CreateUtils.QUARKUS_CORE_BOM_ARTIFACT_ID.equals(bomArtifactId) - ? CreateUtils.resolvePluginInfo(BuildFileMojoBase.class).getVersion() - : null; - } - final QuarkusPlatformDescriptor platform = QuarkusJsonPlatformDescriptorResolver.newInstance() - .setArtifactResolver(new BootstrapAppModelResolver(mvn)) - .setMessageWriter(log) - .resolveFromBom(bomGroupId, bomArtifactId, bomVersion); - QuarkusPlatformConfig.defaultConfigBuilder() - .setPlatformDescriptor(platform) - .build(); + CreateUtils.setGlobalPlatformDescriptor(bomGroupId, bomArtifactId, bomVersion, mvn, getLog()); } doExecute(buildFile); diff --git a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java index b017d034a9697..3e0c846c5685f 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/CreateProjectMojo.java @@ -44,7 +44,6 @@ import org.fusesource.jansi.Ansi; import io.quarkus.bootstrap.resolver.AppModelResolverException; -import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver; import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver; import io.quarkus.cli.commands.AddExtensionResult; import io.quarkus.cli.commands.AddExtensions; @@ -56,10 +55,6 @@ import io.quarkus.maven.components.MavenVersionEnforcer; import io.quarkus.maven.components.Prompter; import io.quarkus.maven.utilities.MojoUtils; -import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; -import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver; -import io.quarkus.platform.tools.config.QuarkusPlatformConfig; -import io.quarkus.platform.tools.maven.MojoMessageWriter; /** * This goal helps in setting up Quarkus Maven project with quarkus-maven-plugin, with sensible defaults @@ -83,12 +78,21 @@ public class CreateProjectMojo extends AbstractMojo { @Parameter(property = "projectVersion") private String projectVersion; - @Parameter(property = "platformGroupId", defaultValue = CreateUtils.DEFAULT_PLATFORM_BOM_GROUP_ID) + /** + * Group ID of the target platform BOM + */ + @Parameter(property = "platformGroupId", required = false) private String bomGroupId; - @Parameter(property = "platformArtifactId", defaultValue = CreateUtils.DEFAULT_PLATFORM_BOM_ARTIFACT_ID) + /** + * Artifact ID of the target platform BOM + */ + @Parameter(property = "platformArtifactId", required = false) private String bomArtifactId; + /** + * Version of the target platform BOM + */ @Parameter(property = "platformVersion", required = false) private String bomVersion; @@ -143,19 +147,7 @@ public void execute() throws MojoExecutionException { } catch (AppModelResolverException e1) { throw new MojoExecutionException("Failed to initialize Maven artifact resolver", e1); } - - if (CreateUtils.QUARKUS_CORE_BOM_ARTIFACT_ID.equals(bomArtifactId) - && (bomVersion == null || bomVersion.isEmpty())) { - bomVersion = CreateUtils.resolvePluginInfo(getClass()).getVersion(); - } - - // We assume platform specified by user refers to a BOM. - final QuarkusPlatformDescriptor platform = QuarkusJsonPlatformDescriptorResolver.newInstance() - .setMessageWriter(new MojoMessageWriter(getLog())) - .setArtifactResolver(new BootstrapAppModelResolver(mvn)) - .resolveFromBom(bomGroupId, bomArtifactId, bomVersion); - - QuarkusPlatformConfig.defaultConfigBuilder().setPlatformDescriptor(platform).build(); + CreateUtils.setGlobalPlatformDescriptor(bomGroupId, bomArtifactId, bomVersion, mvn, getLog()); // We detect the Maven version during the project generation to indicate the user immediately that the installed // version may not be supported. diff --git a/devtools/maven/src/main/java/io/quarkus/maven/CreateUtils.java b/devtools/maven/src/main/java/io/quarkus/maven/CreateUtils.java index ced924d801a01..a8904865d6f25 100644 --- a/devtools/maven/src/main/java/io/quarkus/maven/CreateUtils.java +++ b/devtools/maven/src/main/java/io/quarkus/maven/CreateUtils.java @@ -11,12 +11,19 @@ import org.apache.commons.lang3.StringUtils; import org.apache.maven.model.Plugin; import org.apache.maven.plugin.MojoExecutionException; +import org.apache.maven.plugin.logging.Log; import org.w3c.dom.Document; import org.w3c.dom.Node; import org.w3c.dom.NodeList; +import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver; +import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver; import io.quarkus.bootstrap.util.ZipUtils; import io.quarkus.maven.utilities.MojoUtils; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver; +import io.quarkus.platform.tools.config.QuarkusPlatformConfig; +import io.quarkus.platform.tools.maven.MojoMessageWriter; public final class CreateUtils { @@ -28,6 +35,53 @@ private CreateUtils() { //Not to be constructed } + private static boolean isVersionRange(String versionStr) { + if (versionStr == null || versionStr.isEmpty()) { + return false; + } + char c = versionStr.charAt(0); + if (c == '[' || c == '(') { + return true; + } + c = versionStr.charAt(versionStr.length() - 1); + if (c == ']' || c == ')') { + return true; + } + return versionStr.indexOf(',') >= 0; + } + + static void setGlobalPlatformDescriptor(final String bomGroupId, final String bomArtifactId, final String bomVersion, + MavenArtifactResolver mvn, Log log) throws MojoExecutionException { + + final QuarkusJsonPlatformDescriptorResolver platformResolver = QuarkusJsonPlatformDescriptorResolver.newInstance() + .setMessageWriter(new MojoMessageWriter(log)) + .setArtifactResolver(new BootstrapAppModelResolver(mvn)); + + String groupId = StringUtils.defaultIfBlank(bomGroupId, null); + String artifactId = StringUtils.defaultIfBlank(bomArtifactId, null); + String version = StringUtils.defaultIfBlank(bomVersion, null); + + if (CreateUtils.QUARKUS_CORE_BOM_ARTIFACT_ID.equals(artifactId) + && version == null) { + version = resolvePluginInfo(CreateUtils.class).getVersion(); + } + + final QuarkusPlatformDescriptor platform; + if (version == null) { + if (artifactId == null && groupId == null) { + platform = platformResolver.resolve(); + } else { + platform = platformResolver.resolveLatestFromBom(groupId, artifactId, null); + } + } else if (isVersionRange(version)) { + platform = platformResolver.resolveLatestFromBom(groupId, artifactId, version); + } else { + platform = platformResolver.resolveFromBom(groupId, artifactId, version); + } + + QuarkusPlatformConfig.defaultConfigBuilder().setPlatformDescriptor(platform).build(); + } + public static String getDerivedPath(String className) { String[] resourceClassName = StringUtils.splitByCharacterTypeCamelCase( className.substring(className.lastIndexOf(".") + 1)); diff --git a/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/ResolverSetupCleanup.java b/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/ResolverSetupCleanup.java index 50cc82ce5a60f..f3f03040a05d1 100644 --- a/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/ResolverSetupCleanup.java +++ b/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/ResolverSetupCleanup.java @@ -22,7 +22,7 @@ public class ResolverSetupCleanup { @BeforeEach public void setup() throws Exception { - workDir = IoUtils.createRandomTmpDir(); + workDir = initWorkDir(); repoHome = IoUtils.mkdirs(workDir.resolve("repo")); resolver = initResolver(); repo = TsRepoBuilder.getInstance(resolver, workDir); @@ -30,11 +30,19 @@ public void setup() throws Exception { @AfterEach public void cleanup() { - if(workDir != null) { + if(cleanWorkDir() && workDir != null) { IoUtils.recursiveDelete(workDir); } } + protected Path initWorkDir() { + return IoUtils.createRandomTmpDir(); + } + + protected boolean cleanWorkDir() { + return true; + } + protected BootstrapAppModelResolver initResolver() throws AppModelResolverException { return new BootstrapAppModelResolver(MavenArtifactResolver.builder() .setRepoHome(repoHome) diff --git a/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsArtifact.java b/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsArtifact.java index 70e36a0f9f42e..fb1126b1301b9 100644 --- a/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsArtifact.java +++ b/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsArtifact.java @@ -44,7 +44,7 @@ public static TsArtifact jar(String artifactId, String version) { return new TsArtifact(DEFAULT_GROUP_ID, artifactId, EMPTY, TYPE_JAR, version); } - interface ContentProvider { + public interface ContentProvider { Path getPath(Path workDir) throws IOException; } diff --git a/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsRepoBuilder.java b/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsRepoBuilder.java index 26a3a27361884..4fe5c6fb2227d 100644 --- a/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsRepoBuilder.java +++ b/independent-projects/bootstrap/core/src/test/java/io/quarkus/bootstrap/resolver/TsRepoBuilder.java @@ -66,11 +66,15 @@ public void install(TsArtifact artifact, Path p) { case TsArtifact.TYPE_TXT: p = newTxt(artifact); break; + case TsArtifact.TYPE_POM: + break; default: throw new IllegalStateException("Unsupported artifact type " + artifact.type); } } - install(artifact.toAppArtifact(), p); + if (p != null) { + install(artifact.toAppArtifact(), p); + } } protected void install(AppArtifact artifact, Path file) { diff --git a/independent-projects/tools/common/src/main/java/io/quarkus/platform/tools/ToolsUtils.java b/independent-projects/tools/common/src/main/java/io/quarkus/platform/tools/ToolsUtils.java index 4f6a5e1dbdbd7..cdf5a000a6961 100644 --- a/independent-projects/tools/common/src/main/java/io/quarkus/platform/tools/ToolsUtils.java +++ b/independent-projects/tools/common/src/main/java/io/quarkus/platform/tools/ToolsUtils.java @@ -17,4 +17,8 @@ public static String getProperty(String name) { public static String getProperty(String name, String defaultValue) { return System.getProperty(name, defaultValue); } + + public static boolean isNullOrEmpty(String arg) { + return arg == null || arg.isEmpty(); + } } diff --git a/independent-projects/tools/platform-descriptor-resolver-json/pom.xml b/independent-projects/tools/platform-descriptor-resolver-json/pom.xml index 7a63970cff0da..14d95d8841698 100644 --- a/independent-projects/tools/platform-descriptor-resolver-json/pom.xml +++ b/independent-projects/tools/platform-descriptor-resolver-json/pom.xml @@ -31,11 +31,17 @@ org.jboss.logging jboss-logging - org.junit.jupiter junit-jupiter test + + io.quarkus + quarkus-bootstrap-core + test-jar + test + ${quarkus.version} + diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/PlatformDescriptorLoadingException.java b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/PlatformDescriptorLoadingException.java new file mode 100644 index 0000000000000..f661ccdca9e18 --- /dev/null +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/PlatformDescriptorLoadingException.java @@ -0,0 +1,16 @@ +package io.quarkus.platform.descriptor.resolver.json; + +import java.lang.Exception; + +public class PlatformDescriptorLoadingException extends Exception { + + private static final long serialVersionUID = 1L; + + public PlatformDescriptorLoadingException(String message, Throwable cause) { + super(message, cause); + } + + public PlatformDescriptorLoadingException(String message) { + super(message); + } +} diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java index e72bdae43d6a6..28a289f6320fb 100644 --- a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/QuarkusJsonPlatformDescriptorResolver.java @@ -39,12 +39,15 @@ import io.quarkus.platform.tools.DefaultMessageWriter; import io.quarkus.platform.tools.MessageWriter; import io.quarkus.platform.tools.ToolsConstants; +import io.quarkus.platform.tools.ToolsUtils; /** * Helps resolve the specific or the latest available version of a JSON platform descriptor. */ public class QuarkusJsonPlatformDescriptorResolver { + private static final String DEFAULT_QUARKUS_PLATFORM_VERSION_RANGE = "[0.28.1,2)"; + private static final String DEFAULT_NON_QUARKUS_VERSION_RANGE = "[0,)"; public static final String PROP_PLATFORM_JSON_GROUP_ID = "quarkus.platform.json.groupId"; public static final String PROP_PLATFORM_JSON_ARTIFACT_ID = "quarkus.platform.json.artifactId"; public static final String PROP_PLATFORM_JSON_VERSION = "quarkus.platform.json.version"; @@ -54,6 +57,14 @@ public static QuarkusJsonPlatformDescriptorResolver newInstance() { return new QuarkusJsonPlatformDescriptorResolver(); } + private static String getDefaultVersionRange(String groupId, String artifactId) { + return ToolsConstants.IO_QUARKUS.equals(groupId) + && ("quarkus-bom".equals(artifactId) + || "quarkus-bom-descriptor".equals(artifactId) + || "quarkus-universe-bom".equals(artifactId)) + ? DEFAULT_QUARKUS_PLATFORM_VERSION_RANGE : DEFAULT_NON_QUARKUS_VERSION_RANGE; + } + private String jsonGroupId; private String jsonArtifactId; private String jsonVersion; @@ -134,16 +145,20 @@ public QuarkusPlatformDescriptor resolve() { } } - if(jsonDescriptor != null) { - return loadFromFile(jsonDescriptor); + try { + if (jsonDescriptor != null) { + return loadFromFile(jsonDescriptor); + } + return resolveJsonDescriptor(artifactResolver); + } catch (PlatformDescriptorLoadingException e) { + throw new IllegalStateException("Failed to load Quarkus platform descriptor", e); } - return resolveJsonDescriptor(artifactResolver); } - private QuarkusPlatformDescriptor loadFromFile(Path jsonFile) { + private QuarkusPlatformDescriptor loadFromFile(Path jsonFile) throws PlatformDescriptorLoadingException { log.debug("Loading Quarkus platform descriptor from %s", jsonFile); if(!Files.exists(jsonFile)) { - throw new IllegalStateException("Failed to locate extensions JSON file at " + jsonFile); + throw new IllegalArgumentException("Failed to locate extensions JSON file at " + jsonFile); } // Resolve the Quarkus version used by the platform @@ -154,26 +169,55 @@ private QuarkusPlatformDescriptor loadFromFile(Path jsonFile) { if(quarkusCoreVersion == null) { throw new IllegalStateException("Failed to determine the Quarkus Core version for " + jsonFile); } - } catch (IOException e) { - throw new IllegalStateException("Failed to parse extensions JSON file " + jsonFile); + } catch (RuntimeException | IOException e) { + throw new PlatformDescriptorLoadingException("Failed to parse extensions JSON file " + jsonFile, e); } log.debug("Loaded Quarkus platform is based on Quarkus %s", quarkusCoreVersion); try (InputStream is = Files.newInputStream(jsonFile)) { return loadPlatformDescriptor(artifactResolver, is, quarkusCoreVersion); - } catch (IOException e) { - throw new IllegalStateException("Failed to read " + jsonFile, e); + } catch (Exception e) { + throw new PlatformDescriptorLoadingException("Failed to load Quarkus platform descriptor from " + jsonFile, e); } } - private QuarkusPlatformDescriptor resolveJsonDescriptor(AppModelResolver artifactResolver) { - if(bomArtifactId != null) { + private QuarkusPlatformDescriptor resolveJsonDescriptor(AppModelResolver artifactResolver) throws PlatformDescriptorLoadingException { + if (!ToolsUtils.isNullOrEmpty(bomGroupId) || !ToolsUtils.isNullOrEmpty(bomArtifactId) + || !ToolsUtils.isNullOrEmpty(bomVersion) || !ToolsUtils.isNullOrEmpty(bomVersionRange)) { + if (log.isDebugEnabled()) { + final StringBuilder buf = new StringBuilder(); + buf.append("Resolving Quarkus platform descriptor from the provided BOM coordinates "); + appendArg(buf, bomGroupId); + buf.append(":"); + appendArg(buf, bomArtifactId); + buf.append(":"); + if (!ToolsUtils.isNullOrEmpty(bomVersion)) { + appendArg(buf, bomVersion); + } else if (!ToolsUtils.isNullOrEmpty(bomVersionRange)) { + appendArg(buf, bomVersionRange); + } else { + appendArg(buf, bomVersion); + } + log.debug(buf.toString()); + } return resolveJsonArtifactFromBom(artifactResolver); } - return resolveJsonArtifactFromArgs(artifactResolver); + try { + return resolveJsonArtifactFromArgs(artifactResolver); + } catch (VersionNotAvailableException e) { + final QuarkusPlatformDescriptor platform = resolveJsonArtifactFromBom(artifactResolver); + log.warn(e.getLocalizedMessage() + ", falling back to bundled " + platform.getBomGroupId() + + ":" + platform.getBomArtifactId() + "::pom:" + platform.getBomVersion() + " based on Quarkus " + + platform.getQuarkusVersion()); + return platform; + } + } + + private static void appendArg(StringBuilder buf, String arg) { + buf.append(ToolsUtils.isNullOrEmpty(arg) ? "" : arg); } - private QuarkusPlatformDescriptor resolveJsonArtifactFromArgs(AppModelResolver artifactResolver) { + private QuarkusPlatformDescriptor resolveJsonArtifactFromArgs(AppModelResolver artifactResolver) throws VersionNotAvailableException { String jsonGroupId = this.jsonGroupId; String jsonArtifactId = this.jsonArtifactId; String jsonVersion = this.jsonVersion; @@ -187,7 +231,12 @@ private QuarkusPlatformDescriptor resolveJsonArtifactFromArgs(AppModelResolver a if (jsonVersionRange != null) { // if the range was set using the api, it overrides a possibly set version system property // depending on how this evolves this may or may not be reasonable - jsonVersion = resolveLatestJsonVersion(artifactResolver, jsonGroupId, jsonArtifactId, jsonVersionRange); + try { + jsonVersion = resolveLatestJsonVersion(artifactResolver, jsonGroupId, jsonArtifactId, jsonVersionRange); + } catch (VersionNotAvailableException e) { + throw new IllegalStateException("Failed to resolve the latest version of " + jsonGroupId + ":" + + jsonArtifactId + " from the requested range " + jsonVersionRange, e); + } } else { jsonVersion = getProperty(PROP_PLATFORM_JSON_VERSION); if (jsonVersion == null) { @@ -198,18 +247,52 @@ private QuarkusPlatformDescriptor resolveJsonArtifactFromArgs(AppModelResolver a return loadFromJsonArtifact(artifactResolver, new AppArtifact(jsonGroupId, jsonArtifactId, null, "json", jsonVersion)); } - private QuarkusPlatformDescriptor resolveJsonArtifactFromBom(AppModelResolver artifactResolver) { + private QuarkusPlatformDescriptor resolveJsonArtifactFromBom(AppModelResolver artifactResolver) throws PlatformDescriptorLoadingException { + + // If some of the coordinates are missing, we are trying the default ones + boolean tryingDefaultCoords = false; String bomGroupId = this.bomGroupId; if(bomGroupId == null) { bomGroupId = ToolsConstants.DEFAULT_PLATFORM_BOM_GROUP_ID; + tryingDefaultCoords = true; + } + String bomArtifactId = this.bomArtifactId; + if(bomArtifactId == null) { + bomArtifactId = ToolsConstants.DEFAULT_PLATFORM_BOM_ARTIFACT_ID; + tryingDefaultCoords = true; } + String bomVersion = this.bomVersion; + try { + return loadFromBomCoords(artifactResolver, bomGroupId, bomArtifactId, bomVersion, null); + } catch(Exception e) { + if (!tryingDefaultCoords) { + throw e; + } + log.debug("Failed to resolve the default BOM coordinates, falling back to the bundled platform artifacts"); + } + + Model bundledBom = loadBundledPom(); + bomGroupId = this.bomGroupId == null ? getGroupId(bundledBom) : this.bomGroupId; + if(bomGroupId == null) { + failedDetermineDefaultPlatformCoords(); + } + bomArtifactId = this.bomArtifactId == null ? getArtifactId(bundledBom) : this.bomArtifactId; if(bomArtifactId == null) { - throw new IllegalStateException("Quarkus Platform BOM artifactId is missing"); + failedDetermineDefaultPlatformCoords(); + } + bomVersion = this.bomVersion; + if(bomVersion == null && this.bomVersionRange == null) { + bomVersion = getVersion(bundledBom); } + return loadFromBomCoords(artifactResolver, bomGroupId, bomArtifactId, bomVersion, bundledBom); + } + + private QuarkusPlatformDescriptor loadFromBomCoords(AppModelResolver artifactResolver, String bomGroupId, + String bomArtifactId, String bomVersion, Model bundledBom) throws PlatformDescriptorLoadingException { if(bomVersion == null) { String bomVersionRange = this.bomVersionRange; if(bomVersionRange == null) { - bomVersionRange = "[0,)"; + bomVersionRange = getDefaultVersionRange(bomGroupId, bomArtifactId); } final AppArtifact bomArtifact = new AppArtifact(bomGroupId, bomArtifactId, null, "pom", bomVersionRange); log.debug("Resolving the latest version of %s", bomArtifact); @@ -218,55 +301,44 @@ private QuarkusPlatformDescriptor resolveJsonArtifactFromBom(AppModelResolver ar } catch (AppModelResolverException e) { throw new IllegalStateException("Failed to resolve the latest version of " + bomArtifact, e); } - throw new IllegalStateException("Quarkus Platform BOM version is missing"); + if(bomVersion == null) { + throw new IllegalStateException("Failed to resolve the latest version of " + bomArtifact); + } } log.debug("Resolving Quarkus platform descriptor from %s:%s::pom:%s", bomGroupId, bomArtifactId, bomVersion); - // first check whether the BOM is available on the classpath - final InputStream bomIs = Thread.currentThread().getContextClassLoader().getResourceAsStream("quarkus-bom/pom.xml"); - if(bomIs != null) { - final Model model; - try { - model = MojoUtils.readPom(bomIs); - } catch (IOException e) { - throw new IllegalStateException("Failed to load POM model from the classpath for quarkus-bom/pom.xml", e); - } finally { - try { - bomIs.close(); - } catch (IOException e) { - } - } - // Check whether the BOM on the classpath is matching the requested one - if(bomArtifactId.equals(model.getArtifactId())) { - final Parent bomParent = model.getParent(); - if(bomVersion.equals(model.getVersion() == null ? bomParent.getVersion() : model.getVersion()) - && bomGroupId.equals(model.getGroupId() == null ? bomParent.getGroupId() : model.getGroupId())) { - log.debug("The requested Quarkus platform BOM version is available on the classpath"); - // If the BOM matches, there should also be the JSON file - final InputStream jsonStream = Thread.currentThread().getContextClassLoader() - .getResourceAsStream("quarkus-bom-descriptor/extensions.json"); - if(jsonStream != null) { - // The JSON is available, now there also should be quarkus.properties - final InputStream quarkusPropsStream = Thread.currentThread().getContextClassLoader().getResourceAsStream("quarkus.properties"); - if(quarkusPropsStream != null) { - final Properties props = new Properties(); - try { - props.load(quarkusPropsStream); - } catch(IOException e) { - throw new IllegalStateException("Failed to load quarkus.properties from the classpath", e); - } - final String quarkusVersion = props.getProperty("plugin-version"); - if(quarkusVersion == null) { - throw new IllegalStateException("quarkus.properties loaded from the classpath is missing plugin-version property"); - } - return loadPlatformDescriptor(artifactResolver,jsonStream, quarkusVersion); - } else { - log.debug("Failed to locate quarkus.properties on the classpath"); - } - } else { - log.debug("Failed to locate Quarkus JSON platform descriptor on the classpath"); + bundledBom = loadBundledPomIfNull(bundledBom); + // Check whether the BOM on the classpath is matching the requested one + if(bundledBom != null + && bomArtifactId.equals(getArtifactId(bundledBom)) + && bomVersion.equals(getVersion(bundledBom)) + && bomGroupId.equals(getGroupId(bundledBom))) { + log.debug("The requested Quarkus platform BOM version is available on the classpath"); + // If the BOM matches, there should also be the JSON file + final InputStream jsonStream = Thread.currentThread().getContextClassLoader() + .getResourceAsStream("quarkus-bom-descriptor/extensions.json"); + if (jsonStream != null) { + // The JSON is available, now there also should be quarkus.properties + final InputStream quarkusPropsStream = Thread.currentThread().getContextClassLoader() + .getResourceAsStream("quarkus.properties"); + if (quarkusPropsStream != null) { + final Properties props = new Properties(); + try { + props.load(quarkusPropsStream); + } catch (IOException e) { + throw new IllegalStateException("Failed to load quarkus.properties from the classpath", e); + } + final String quarkusVersion = props.getProperty("plugin-version"); + if (quarkusVersion == null) { + throw new IllegalStateException( + "quarkus.properties loaded from the classpath is missing plugin-version property"); } + return loadPlatformDescriptor(artifactResolver, jsonStream, quarkusVersion); + } else { + log.debug("Failed to locate quarkus.properties on the classpath"); } + } else { + log.debug("Failed to locate Quarkus JSON platform descriptor on the classpath"); } } @@ -274,10 +346,16 @@ private QuarkusPlatformDescriptor resolveJsonArtifactFromBom(AppModelResolver ar return loadFromJsonArtifact(artifactResolver, new AppArtifact(bomGroupId, bomArtifactId, null, "json", bomVersion)); } + private void failedDetermineDefaultPlatformCoords() { + throw new IllegalStateException("Failed to determine the Maven coordinates of the default Quarkus platform"); + } + private QuarkusPlatformDescriptor loadFromJsonArtifact(AppModelResolver artifactResolver, AppArtifact jsonArtifact) { try { log.debug("Attempting to resolve Quarkus JSON platform descriptor as %s", jsonArtifact); return loadFromFile(artifactResolver.resolve(jsonArtifact)); + } catch(PlatformDescriptorLoadingException e) { + throw new IllegalStateException("Failed to load Quarkus platform descriptor from " + jsonArtifact, e); } catch (Exception e) { log.debug("Failed to resolve %s due to %s", jsonArtifact, e); // it didn't work, now we are trying artifactId-descriptor-json @@ -293,7 +371,7 @@ private QuarkusPlatformDescriptor loadFromJsonArtifact(AppModelResolver artifact @SuppressWarnings("rawtypes") private QuarkusPlatformDescriptor loadPlatformDescriptor(AppModelResolver mvn, final InputStream jsonStream, - String quarkusCoreVersion) { + String quarkusCoreVersion) throws PlatformDescriptorLoadingException { ClassLoader jsonDescrLoaderCl = null; @@ -305,7 +383,7 @@ private QuarkusPlatformDescriptor loadPlatformDescriptor(AppModelResolver mvn, f try { props.load(is); } catch(IOException e) { - throw new IllegalStateException("Failed to load " + pomPropsPath + " from the classpath", e); + throw new PlatformDescriptorLoadingException("Failed to load " + pomPropsPath + " from the classpath", e); } final String version = props.getProperty("version"); if(quarkusCoreVersion.equals(version)) { @@ -329,7 +407,7 @@ private QuarkusPlatformDescriptor loadPlatformDescriptor(AppModelResolver mvn, f log.debug("Quarkus platform resources will be loaded from %s", path); jsonDescrUrl = path.toUri().toURL(); } catch (Exception e) { - throw new IllegalStateException("Failed to resolve " + jsonDescrArtifact, e); + throw new PlatformDescriptorLoadingException("Failed to resolve " + jsonDescrArtifact, e); } jsonDescrLoaderCl = new URLClassLoader(new URL[] {jsonDescrUrl}, Thread.currentThread().getContextClassLoader()); externalLoader = true; @@ -339,12 +417,12 @@ private QuarkusPlatformDescriptor loadPlatformDescriptor(AppModelResolver mvn, f final Iterator i = ServiceLoader .load(QuarkusJsonPlatformDescriptorLoader.class, jsonDescrLoaderCl).iterator(); if (!i.hasNext()) { - throw new IllegalStateException( + throw new PlatformDescriptorLoadingException( "Failed to locate an implementation of " + QuarkusJsonPlatformDescriptorLoader.class.getName()); } final QuarkusJsonPlatformDescriptorLoader jsonDescrLoader = i.next(); if (i.hasNext()) { - throw new IllegalStateException( + throw new PlatformDescriptorLoadingException( "Located more than one implementation of " + QuarkusJsonPlatformDescriptorLoader.class.getName()); } final ArtifactResolver loaderResolver = new ArtifactResolver() { @@ -381,16 +459,20 @@ public List getManagedDependencies(String groupId, String artifactId } }; - return jsonDescrLoader.load( - new QuarkusJsonPlatformDescriptorLoaderContext( - loaderResolver, - resourceLoader == null ? new ClassPathResourceLoader() : resourceLoader, - log) { - @Override - public T parseJson(Function parser) { - return parser.apply(jsonStream); - } - }); + try { + return jsonDescrLoader.load( + new QuarkusJsonPlatformDescriptorLoaderContext( + loaderResolver, + resourceLoader == null ? new ClassPathResourceLoader() : resourceLoader, + log) { + @Override + public T parseJson(Function parser) { + return parser.apply(jsonStream); + } + }); + } catch (Exception e) { + throw new PlatformDescriptorLoadingException("Failed to load Quarkus platform descriptor", e); + } } finally { if (externalLoader) { try { @@ -401,28 +483,93 @@ public T parseJson(Function parser) { } } - private String resolveLatestJsonVersion(AppModelResolver artifactResolver, String groupId, String artifactId, String versionRange) { + private String resolveLatestJsonVersion(AppModelResolver artifactResolver, String groupId, String artifactId, String versionRange) throws VersionNotAvailableException { if(versionRange == null) { versionRange = getProperty(PROP_PLATFORM_JSON_VERSION_RANGE); if(versionRange == null) { - versionRange = "[0,)"; + versionRange = getDefaultVersionRange(groupId, artifactId); } } try { return resolveLatestFromVersionRange(artifactResolver, groupId, artifactId, null, "json", versionRange); } catch (AppModelResolverException e) { - throw new IllegalStateException("Failed to resolve the latest JSON platform version of " + groupId + ":" + artifactId + "::json:" + versionRange); + throw new VersionNotAvailableException("Failed to resolve the latest JSON platform version of " + groupId + ":" + artifactId + "::json:" + versionRange); } } private String resolveLatestFromVersionRange(AppModelResolver mvn, String groupId, String artifactId, String classifier, String type, final String versionRange) - throws AppModelResolverException { + throws AppModelResolverException, VersionNotAvailableException { final AppArtifact appArtifact = new AppArtifact(groupId, artifactId, classifier, type, versionRange); log.debug("Resolving the latest version of " + appArtifact); final String latestVersion = mvn.getLatestVersionFromRange(appArtifact, versionRange); if(latestVersion == null) { - throw new IllegalStateException("Failed to resolve the latest version of " + appArtifact); + throw new VersionNotAvailableException("Failed to resolve the latest version of " + appArtifact); } return latestVersion; } + + private Model loadBundledPomIfNull(Model model) { + return model == null ? loadBundledPom() : model; + } + + private Model loadBundledPom() { + final InputStream bomIs = Thread.currentThread().getContextClassLoader().getResourceAsStream("quarkus-bom/pom.xml"); + if(bomIs == null) { + log.debug("Failed to locate quarkus-bom/pom.xml on the classpath"); + return null; + } + try { + return MojoUtils.readPom(bomIs); + } catch (IOException e) { + throw new IllegalStateException("Failed to load POM model from the classpath for quarkus-bom/pom.xml", e); + } finally { + try { + bomIs.close(); + } catch (IOException e) { + } + } + } + + private static String getGroupId(Model model) { + if(model == null) { + return null; + } + String groupId = model.getGroupId(); + if(groupId != null) { + return groupId; + } + final Parent parent = model.getParent(); + if(parent != null) { + groupId = parent.getGroupId(); + if(groupId != null) { + return groupId; + } + } + throw new IllegalStateException("Failed to determine the groupId for the POM of " + model.getArtifactId()); + } + + private static String getArtifactId(Model model) { + if(model == null) { + return null; + } + return model.getArtifactId(); + } + + private static String getVersion(Model model) { + if(model == null) { + return null; + } + String version = model.getVersion(); + if(version != null) { + return version; + } + final Parent parent = model.getParent(); + if(parent != null) { + version = parent.getVersion(); + if(version != null) { + return version; + } + } + throw new IllegalStateException("Failed to determine the version for the POM of " + model.getArtifactId()); + } } diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/VersionNotAvailableException.java b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/VersionNotAvailableException.java new file mode 100644 index 0000000000000..cea8276f63991 --- /dev/null +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/VersionNotAvailableException.java @@ -0,0 +1,14 @@ +package io.quarkus.platform.descriptor.resolver.json; + +public class VersionNotAvailableException extends Exception { + + private static final long serialVersionUID = 1L; + + public VersionNotAvailableException(String message, Throwable cause) { + super(message, cause); + } + + public VersionNotAvailableException(String message) { + super(message); + } +} diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/demo/JsonDescriptorResolverDemo.java b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/demo/JsonDescriptorResolverDemo.java index 2dec28b56a37d..bdae5af02551c 100644 --- a/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/demo/JsonDescriptorResolverDemo.java +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/main/java/io/quarkus/platform/descriptor/resolver/json/demo/JsonDescriptorResolverDemo.java @@ -1,5 +1,7 @@ package io.quarkus.platform.descriptor.resolver.json.demo; +import io.quarkus.bootstrap.resolver.BootstrapAppModelResolver; +import io.quarkus.bootstrap.resolver.maven.MavenArtifactResolver; import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver; import io.quarkus.platform.tools.DefaultMessageWriter; @@ -13,7 +15,13 @@ public static void main(String... args) throws Exception { final QuarkusPlatformDescriptor platform = QuarkusJsonPlatformDescriptorResolver.newInstance() .setMessageWriter(log) - .resolveFromJsonArtifactId("quarkus-bom-descriptor-json"); + .setArtifactResolver( + new BootstrapAppModelResolver( + MavenArtifactResolver.builder() + .setOffline(true) + .build())) + .resolve(); + //.resolveFromJsonArtifactId("quarkus-bom-descriptor-json"); log.info("Platform BOM: " + platform.getBomGroupId() + ":" + platform.getBomArtifactId() + ":" + platform.getBomVersion()); log.info("Extensions total: " + platform.getExtensions().size()); diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/QuarkusJsonPlatformDescriptorResolverTest.java b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/QuarkusJsonPlatformDescriptorResolverTest.java new file mode 100644 index 0000000000000..5b0321216cefb --- /dev/null +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/QuarkusJsonPlatformDescriptorResolverTest.java @@ -0,0 +1,171 @@ +package io.quarkus.platform.descriptor.resolver.json.test; + +import static io.quarkus.platform.tools.ToolsConstants.IO_QUARKUS; +import static io.quarkus.platform.tools.ToolsConstants.QUARKUS_CORE_ARTIFACT_ID; +import static io.quarkus.platform.tools.ToolsConstants.DEFAULT_PLATFORM_BOM_ARTIFACT_ID; +import static io.quarkus.platform.tools.ToolsConstants.DEFAULT_PLATFORM_BOM_GROUP_ID; + +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; + +import java.nio.file.Path; + +import org.junit.jupiter.api.AfterAll; +import org.junit.jupiter.api.BeforeEach; +import org.junit.jupiter.api.Test; + +import io.quarkus.bootstrap.model.AppArtifact; +import io.quarkus.bootstrap.resolver.ResolverSetupCleanup; +import io.quarkus.bootstrap.resolver.TsArtifact; +import io.quarkus.bootstrap.resolver.TsDependency; +import io.quarkus.bootstrap.util.IoUtils; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import io.quarkus.platform.descriptor.resolver.json.QuarkusJsonPlatformDescriptorResolver; +import io.quarkus.platform.tools.DefaultMessageWriter; +import io.quarkus.platform.tools.MessageWriter; +import io.quarkus.platform.tools.ToolsConstants; + +public class QuarkusJsonPlatformDescriptorResolverTest extends ResolverSetupCleanup { + + private static Path testDir; + + private MessageWriter log = new DefaultMessageWriter(); + + @BeforeEach + @Override + public void setup() throws Exception { + if(workDir != null) { + return; + } + super.setup(); + testDir = workDir; + doSetup(); + } + + @Override + protected boolean cleanWorkDir() { + return false; + } + + @AfterAll + public static void afterAll() throws Exception { + if(testDir != null) { + IoUtils.recursiveDelete(testDir); + } + } + + protected void doSetup() throws Exception { + + final TsArtifact quarkusCore = new TsArtifact(IO_QUARKUS, QUARKUS_CORE_ARTIFACT_ID, null, "jar", "0.28.5"); + install(quarkusCore, newJar().getPath(workDir)); + + final TsArtifact quarkusPlatformDescriptorJson = new TsArtifact(IO_QUARKUS, "quarkus-platform-descriptor-json", null, "jar", "0.28.5"); + install(quarkusPlatformDescriptorJson, newJar().getPath(workDir)); + + // install a few universe versions with the default GA + installDefaultUniverse(quarkusCore, "0.28.5"); + installDefaultUniverse(quarkusCore, "0.28.6"); + installDefaultUniverse(quarkusCore, "0.28.7"); + + // install a universe with a custom GA and JSON descriptor with `-descriptor-json` suffix + TsArtifact universeBom = new TsArtifact(DEFAULT_PLATFORM_BOM_GROUP_ID, "other-universe", null, "pom", "0.28.8") + .addManagedDependency(new TsDependency(quarkusCore)); + install(universeBom); + final TsArtifact universeJson = new TsArtifact(DEFAULT_PLATFORM_BOM_GROUP_ID, "other-universe" + "-descriptor-json", null, "json", "0.28.8") + .setContent(new TestPlatformJsonDescriptorProvider(universeBom)); + install(universeJson); + + } + + @Test + public void testResolve() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolve(); + assertDefaultPlatform(platform, "0.28.7"); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromJsonVersion() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolveFromJson(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, "0.28.6"); + assertDefaultPlatform(platform, "0.28.6"); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromJsonFile() throws Exception { + final Path jsonPath = resolver.resolve(new AppArtifact(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, null, "json", "0.28.5")); + final QuarkusPlatformDescriptor platform = newResolver().resolveFromJson(jsonPath); + assertDefaultPlatform(platform, "0.28.5"); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromBomWithDescriptorJsonPrefix() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolveFromBom(DEFAULT_PLATFORM_BOM_GROUP_ID, "other-universe", "0.28.8"); + assertNotNull(platform); + assertEquals(ToolsConstants.IO_QUARKUS, platform.getBomGroupId()); + assertEquals("other-universe", platform.getBomArtifactId()); + assertEquals("0.28.8", platform.getBomVersion()); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromJsonWithDescriptorJsonPrefix() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolveLatestFromJson(DEFAULT_PLATFORM_BOM_GROUP_ID, "other-universe" + "-descriptor-json", null); + assertNotNull(platform); + assertEquals(ToolsConstants.IO_QUARKUS, platform.getBomGroupId()); + assertEquals("other-universe", platform.getBomArtifactId()); + assertEquals("0.28.8", platform.getBomVersion()); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromLatestJson() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolveLatestFromJson(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, null); + assertDefaultPlatform(platform, "0.28.7"); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromLatestJsonWithRange() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolveLatestFromJson(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, "[0,0.28.6]"); + assertDefaultPlatform(platform, "0.28.6"); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromLatestBom() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolveLatestFromBom(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, null); + assertDefaultPlatform(platform, "0.28.7"); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + @Test + public void testResolveFromLatestBomWithRange() throws Exception { + final QuarkusPlatformDescriptor platform = newResolver().resolveLatestFromJson(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, "[0,0.28.6]"); + assertDefaultPlatform(platform, "0.28.6"); + assertEquals("0.28.5", platform.getQuarkusVersion()); + } + + private void installDefaultUniverse(final TsArtifact quarkusCore, String platformVersion) { + final TsArtifact universeBom = new TsArtifact(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, null, "pom", platformVersion) + .addManagedDependency(new TsDependency(quarkusCore)); + install(universeBom); + final TsArtifact universeJson = new TsArtifact(DEFAULT_PLATFORM_BOM_GROUP_ID, DEFAULT_PLATFORM_BOM_ARTIFACT_ID, null, "json", platformVersion) + .setContent(new TestPlatformJsonDescriptorProvider(universeBom)); + install(universeJson); + } + + private QuarkusJsonPlatformDescriptorResolver newResolver() { + return QuarkusJsonPlatformDescriptorResolver.newInstance() + .setMessageWriter(log) + .setArtifactResolver(resolver); + } + + private static void assertDefaultPlatform(QuarkusPlatformDescriptor platform, String version) { + assertNotNull(platform); + assertEquals(ToolsConstants.IO_QUARKUS, platform.getBomGroupId()); + assertEquals(ToolsConstants.DEFAULT_PLATFORM_BOM_ARTIFACT_ID, platform.getBomArtifactId()); + assertEquals(version, platform.getBomVersion()); + } +} diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java new file mode 100644 index 0000000000000..647fe459a6dcb --- /dev/null +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestJsonPlatformDescriptorLoader.java @@ -0,0 +1,94 @@ +package io.quarkus.platform.descriptor.resolver.json.test; + +import java.io.IOException; +import java.io.InputStreamReader; +import java.util.Collections; +import java.util.List; + +import org.apache.maven.model.Dependency; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonObject; +import com.eclipsesource.json.JsonValue; + +import io.quarkus.dependencies.Category; +import io.quarkus.dependencies.Extension; +import io.quarkus.platform.descriptor.QuarkusPlatformDescriptor; +import io.quarkus.platform.descriptor.ResourceInputStreamConsumer; +import io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoader; +import io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoaderContext; + +public class TestJsonPlatformDescriptorLoader implements QuarkusJsonPlatformDescriptorLoader { + + @Override + public QuarkusPlatformDescriptor load(QuarkusJsonPlatformDescriptorLoaderContext context) { + final JsonObject json = context.parseJson(s -> { + try (InputStreamReader reader = new InputStreamReader(s)) { + return Json.parse(reader).asObject(); + } catch (IOException e) { + throw new IllegalStateException("Failed to parse JSON descriptor", e); + } + }); + + JsonValue jsonValue = getRequiredAttr(json, "bom"); + final JsonObject bom = jsonValue.asObject(); + + jsonValue = getRequiredAttr(json, "quarkus-core-version"); + final String quarkusVersion = jsonValue.asString(); + + return new QuarkusPlatformDescriptor() { + + @Override + public String getBomGroupId() { + return bom.getString("groupId", null); + } + + @Override + public String getBomArtifactId() { + return bom.getString("artifactId", null); + } + + @Override + public String getBomVersion() { + return bom.getString("version", null); + } + + @Override + public String getQuarkusVersion() { + return quarkusVersion; + } + + @Override + public List getManagedDependencies() { + return Collections.emptyList(); + } + + @Override + public List getExtensions() { + return Collections.emptyList(); + } + + @Override + public List getCategories() { + return Collections.emptyList(); + } + + @Override + public String getTemplate(String name) { + return null; + } + + @Override + public T loadResource(String name, ResourceInputStreamConsumer consumer) throws IOException { + return null; + }}; + } + + private JsonValue getRequiredAttr(final JsonObject json, String name) { + final JsonValue jsonValue = json.get(name); + if(jsonValue == null) { + throw new IllegalStateException("Failed to locate '" + name + "' attribute in the JSON descriptor"); + } + return jsonValue; + } +} diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestPlatformJsonDescriptorProvider.java b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestPlatformJsonDescriptorProvider.java new file mode 100644 index 0000000000000..dd39362676909 --- /dev/null +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/test/java/io/quarkus/platform/descriptor/resolver/json/test/TestPlatformJsonDescriptorProvider.java @@ -0,0 +1,53 @@ +package io.quarkus.platform.descriptor.resolver.json.test; + +import java.io.BufferedWriter; +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +import org.apache.maven.model.Dependency; +import org.apache.maven.model.Model; + +import com.eclipsesource.json.Json; +import com.eclipsesource.json.JsonObject; + +import io.quarkus.bootstrap.resolver.TsArtifact; +import io.quarkus.platform.tools.ToolsConstants; + +public class TestPlatformJsonDescriptorProvider implements TsArtifact.ContentProvider { + + private final TsArtifact bomArtifact; + + + public TestPlatformJsonDescriptorProvider(TsArtifact bomArtifact) { + this.bomArtifact = bomArtifact; + } + + + @Override + public Path getPath(Path workDir) throws IOException { + final Model model = bomArtifact.getPomModel(); + + final JsonObject json = Json.object(); + + json.set("bom", Json.object().set("groupId", model.getGroupId()).set("artifactId", model.getArtifactId()).set("version", model.getVersion())); + + String coreVersion = null; + for(Dependency dep : model.getDependencyManagement().getDependencies()) { + if(dep.getArtifactId().equals(ToolsConstants.QUARKUS_CORE_ARTIFACT_ID) + && dep.getGroupId().equals(ToolsConstants.QUARKUS_CORE_GROUP_ID)) { + coreVersion = dep.getVersion(); + } + } + if(coreVersion == null) { + throw new IllegalStateException("Failed to locate " + ToolsConstants.QUARKUS_CORE_GROUP_ID + ":" + ToolsConstants.QUARKUS_CORE_ARTIFACT_ID + " among the managed dependencies"); + } + json.set("quarkus-core-version", coreVersion); + + final Path jsonPath = workDir.resolve(bomArtifact.getArtifactFileName()); + try(BufferedWriter writer = Files.newBufferedWriter(jsonPath)) { + json.writeTo(writer); + } + return jsonPath; + } +} diff --git a/independent-projects/tools/platform-descriptor-resolver-json/src/test/resources/META-INF/services/io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoader b/independent-projects/tools/platform-descriptor-resolver-json/src/test/resources/META-INF/services/io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoader new file mode 100644 index 0000000000000..3698a45f9f4bd --- /dev/null +++ b/independent-projects/tools/platform-descriptor-resolver-json/src/test/resources/META-INF/services/io.quarkus.platform.descriptor.loader.json.QuarkusJsonPlatformDescriptorLoader @@ -0,0 +1 @@ +io.quarkus.platform.descriptor.resolver.json.test.TestJsonPlatformDescriptorLoader \ No newline at end of file diff --git a/integration-tests/kotlin/src/test/java/io/quarkus/kotlin/maven/it/KotlinCreateMavenProjectIT.java b/integration-tests/kotlin/src/test/java/io/quarkus/kotlin/maven/it/KotlinCreateMavenProjectIT.java index c16e454efa6bb..421109bbc8ee5 100644 --- a/integration-tests/kotlin/src/test/java/io/quarkus/kotlin/maven/it/KotlinCreateMavenProjectIT.java +++ b/integration-tests/kotlin/src/test/java/io/quarkus/kotlin/maven/it/KotlinCreateMavenProjectIT.java @@ -73,6 +73,10 @@ public void testProjectGenerationFromScratchForKotlin() throws MavenInvocationEx private InvocationResult setup(Properties params) throws MavenInvocationException, FileNotFoundException, UnsupportedEncodingException { + + params.setProperty("platformArtifactId", "quarkus-bom"); + params.setProperty("platformVersion", MojoUtils.getPluginVersion()); + InvocationRequest request = new DefaultInvocationRequest(); request.setBatchMode(true); request.setGoals(Collections.singletonList( diff --git a/integration-tests/maven/src/it/setup-on-existing-pom-it/invoker.properties b/integration-tests/maven/src/it/setup-on-existing-pom-it/invoker.properties index 5d553b40e4c98..0d55bdb0e593d 100644 --- a/integration-tests/maven/src/it/setup-on-existing-pom-it/invoker.properties +++ b/integration-tests/maven/src/it/setup-on-existing-pom-it/invoker.properties @@ -1 +1 @@ -invoker.goals=io.quarkus:quarkus-maven-plugin:${project.version}:create +invoker.goals=io.quarkus:quarkus-maven-plugin:${project.version}:create -DplatformArtifactId=quarkus-bom -DplatformVersion=${project.version} diff --git a/integration-tests/maven/src/it/setup-on-min-pom-it/invoker.properties b/integration-tests/maven/src/it/setup-on-min-pom-it/invoker.properties index 5d553b40e4c98..0d55bdb0e593d 100644 --- a/integration-tests/maven/src/it/setup-on-min-pom-it/invoker.properties +++ b/integration-tests/maven/src/it/setup-on-min-pom-it/invoker.properties @@ -1 +1 @@ -invoker.goals=io.quarkus:quarkus-maven-plugin:${project.version}:create +invoker.goals=io.quarkus:quarkus-maven-plugin:${project.version}:create -DplatformArtifactId=quarkus-bom -DplatformVersion=${project.version} diff --git a/integration-tests/maven/src/it/setup-with-custom-quarkus-version-it/invoker.properties b/integration-tests/maven/src/it/setup-with-custom-quarkus-version-it/invoker.properties index 96c741d97edb0..849085b376d85 100644 --- a/integration-tests/maven/src/it/setup-with-custom-quarkus-version-it/invoker.properties +++ b/integration-tests/maven/src/it/setup-with-custom-quarkus-version-it/invoker.properties @@ -1 +1 @@ -invoker.goals=io.quarkus:quarkus-maven-plugin:${project.version}:create -DquarkusVersion=0.0.0 +invoker.goals=io.quarkus:quarkus-maven-plugin:${project.version}:create -DquarkusVersion=0.0.0 -DplatformArtifactId=quarkus-bom -DplatformVersion=${project.version} diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/AddExtensionIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/AddExtensionIT.java index d95539f64cfc3..f7edcb8e8a024 100644 --- a/integration-tests/maven/src/test/java/io/quarkus/maven/it/AddExtensionIT.java +++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/AddExtensionIT.java @@ -108,6 +108,9 @@ private void addExtension(boolean plural, String ext) request.setGoals(Collections.singletonList( MojoUtils.getPluginKey() + ":" + MojoUtils.getPluginVersion() + ":add-extension")); Properties properties = new Properties(); + properties.setProperty("platformGroupId", "io.quarkus"); + properties.setProperty("platformArtifactId", "quarkus-bom"); + properties.setProperty("platformVersion", MojoUtils.getPluginVersion()); if (plural) { properties.setProperty("extensions", ext); } else { diff --git a/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java b/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java index 9be37bfd53097..f01404a70d330 100644 --- a/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java +++ b/integration-tests/maven/src/test/java/io/quarkus/maven/it/CreateProjectMojoIT.java @@ -21,6 +21,7 @@ import io.quarkus.maven.it.verifier.RunningInvoker; import io.quarkus.maven.utilities.MojoUtils; +import io.quarkus.platform.tools.ToolsConstants; /** * @author Clement Escoffier @@ -312,6 +313,11 @@ public void generateNewProjectAndRun() throws Exception { private InvocationResult setup(Properties params) throws MavenInvocationException, FileNotFoundException, UnsupportedEncodingException { + + params.setProperty("platformGroupId", ToolsConstants.IO_QUARKUS); + params.setProperty("platformArtifactId", "quarkus-bom"); + params.setProperty("platformVersion", MojoUtils.getPluginVersion()); + InvocationRequest request = new DefaultInvocationRequest(); request.setBatchMode(true); request.setGoals(Collections.singletonList( diff --git a/integration-tests/scala/src/test/java/io/quarkus/scala/maven/it/ScalaCreateMavenProjectIT.java b/integration-tests/scala/src/test/java/io/quarkus/scala/maven/it/ScalaCreateMavenProjectIT.java index 2958043055689..d02c00e27fd6d 100644 --- a/integration-tests/scala/src/test/java/io/quarkus/scala/maven/it/ScalaCreateMavenProjectIT.java +++ b/integration-tests/scala/src/test/java/io/quarkus/scala/maven/it/ScalaCreateMavenProjectIT.java @@ -73,6 +73,10 @@ public void testProjectGenerationFromScratchForScala() throws MavenInvocationExc private InvocationResult setup(Properties params) throws MavenInvocationException, FileNotFoundException, UnsupportedEncodingException { + + params.setProperty("platformArtifactId", "quarkus-bom"); + params.setProperty("platformVersion", MojoUtils.getPluginVersion()); + InvocationRequest request = new DefaultInvocationRequest(); request.setBatchMode(true); request.setGoals(Collections.singletonList(