From 923cc89719e4dfd181cc165f92ac56ffe4581b90 Mon Sep 17 00:00:00 2001 From: Jiri Ondrusek Date: Mon, 20 Apr 2026 16:22:51 +0200 Subject: [PATCH] CAMEL-23353: Add configurable default Maven repositories and Quarkus platform registry resolution Co-authored-by: Croway --- .../jbang/core/commands/ExportQuarkus.java | 6 ++ .../dsl/jbang/core/common/QuarkusHelper.java | 89 ++++++++++++++----- .../tooling/maven/MavenDownloaderImpl.java | 38 ++++++++ 3 files changed, 109 insertions(+), 24 deletions(-) diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java index 9b58bf18dad8f..84ef66c6da08e 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/commands/ExportQuarkus.java @@ -34,6 +34,7 @@ import org.apache.camel.dsl.jbang.core.common.CatalogLoader; import org.apache.camel.dsl.jbang.core.common.CommandLineHelper; import org.apache.camel.dsl.jbang.core.common.PathUtils; +import org.apache.camel.dsl.jbang.core.common.QuarkusHelper; import org.apache.camel.dsl.jbang.core.common.RuntimeUtil; import org.apache.camel.dsl.jbang.core.common.VersionHelper; import org.apache.camel.tooling.maven.MavenGav; @@ -136,6 +137,11 @@ public Integer export() throws Exception { appJar = "target" + File.separator + ids[1] + "-" + ids[2] + ".jar"; } copyReadme(BUILD_DIR, appJar); + // resolve Quarkus platform version from registry (if available) + String resolved = QuarkusHelper.resolveQuarkusPlatformVersion(quarkusVersion); + if (resolved != null) { + quarkusVersion = resolved; + } // gather dependencies Set deps = resolveDependencies(settings, profile); // copy local lib JARs diff --git a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/QuarkusHelper.java b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/QuarkusHelper.java index 2221c7c63516b..a1fb72c61bc56 100644 --- a/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/QuarkusHelper.java +++ b/dsl/camel-jbang/camel-jbang-core/src/main/java/org/apache/camel/dsl/jbang/core/common/QuarkusHelper.java @@ -68,6 +68,59 @@ public static void resolveQuarkusPlatformVersions( Function runtimeVersionFunc, BiConsumer quarkusVersionSetter) { + JsonArray streams = fetchPlatformStreams(); + if (streams == null) { + return; + } + + // keep the row with the highest runtime version per major.minor stream + BinaryOperator keepLatest = (a, b) -> VersionHelper.compare( + runtimeVersionFunc.apply(a), runtimeVersionFunc.apply(b)) >= 0 ? a : b; + + Map latestPerStream = rows.stream() + .filter(row -> runtimeVersionFunc.apply(row) != null) + .collect(Collectors.toMap( + row -> VersionHelper.getMajorMinorVersion(runtimeVersionFunc.apply(row)), + Function.identity(), + keepLatest)); + + // match each major.minor against registry streams and set the quarkus version + latestPerStream.forEach((majorMinor, row) -> findStreamVersion(streams, majorMinor, "quarkus-core-version") + .ifPresent(version -> quarkusVersionSetter.accept(row, version))); + } + + /** + * Resolves the Quarkus platform BOM version by matching the build-time version's major.minor against the Quarkus + * platform registry. + *

+ * This is used by export/run commands to query the registry for the correct platform BOM version instead of using + * the build-time constant. The registry may have a newer compatible version. + * + * @param buildTimeVersion the build-time Quarkus version (e.g., "3.15.7.something") + * @return the resolved platform BOM version from the registry, or the original buildTimeVersion if + * resolution fails + */ + public static String resolveQuarkusPlatformVersion(String buildTimeVersion) { + if (buildTimeVersion == null) { + return null; + } + + JsonArray streams = fetchPlatformStreams(); + if (streams == null) { + return buildTimeVersion; + } + + String majorMinor = VersionHelper.getMajorMinorVersion(buildTimeVersion); + Optional resolved = findStreamVersion(streams, majorMinor, "version"); + return resolved.orElse(buildTimeVersion); + } + + /** + * Fetches the platform streams array from the Quarkus platform registry. + * + * @return the streams JsonArray, or null if the registry is unreachable or the response is invalid + */ + private static JsonArray fetchPlatformStreams() { try { HttpClient hc = HttpClient.newHttpClient(); HttpResponse res = hc.send( @@ -80,38 +133,26 @@ public static void resolveQuarkusPlatformVersions( JsonObject json = (JsonObject) Jsoner.deserialize(res.body()); JsonArray platforms = json.getCollection("platforms"); if (platforms == null || platforms.isEmpty()) { - return; + return null; } JsonObject platform = platforms.getMap(0); - JsonArray streams = platform.getCollection("streams"); - if (streams == null) { - return; - } - - // keep the row with the highest runtime version per major.minor stream - BinaryOperator keepLatest = (a, b) -> VersionHelper.compare( - runtimeVersionFunc.apply(a), runtimeVersionFunc.apply(b)) >= 0 ? a : b; - - Map latestPerStream = rows.stream() - .filter(row -> runtimeVersionFunc.apply(row) != null) - .collect(Collectors.toMap( - row -> VersionHelper.getMajorMinorVersion(runtimeVersionFunc.apply(row)), - Function.identity(), - keepLatest)); - - // match each major.minor against registry streams and set the quarkus version - latestPerStream.forEach((majorMinor, row) -> findQuarkusCoreVersion(streams, majorMinor) - .ifPresent(version -> quarkusVersionSetter.accept(row, version))); + return platform.getCollection("streams"); } } catch (Exception e) { - // ignore - if the registry is not reachable within 2 seconds, skip + // ignore - if the registry is not reachable within 2 seconds, return null } + return null; } /** - * Finds the quarkus-core-version from the registry streams that matches the given major.minor stream ID. + * Finds a version field from the registry streams that matches the given major.minor stream ID. + * + * @param streams the streams array from the registry + * @param majorMinor the major.minor version to match (e.g., "3.15") + * @param fieldName the field name to extract from the release ("version" or "quarkus-core-version") + * @return the version string, or empty if not found */ - private static Optional findQuarkusCoreVersion(JsonArray streams, String majorMinor) { + private static Optional findStreamVersion(JsonArray streams, String majorMinor, String fieldName) { return streams.stream() .map(s -> (JsonObject) s) .filter(stream -> majorMinor.equals(stream.getString("id"))) @@ -119,6 +160,6 @@ private static Optional findQuarkusCoreVersion(JsonArray streams, String .map(stream -> (JsonArray) stream.getCollection("releases")) .filter(releases -> !releases.isEmpty()) .map(releases -> (JsonObject) releases.getMap(0)) - .map(release -> release.getString("quarkus-core-version")); + .map(release -> release.getString(fieldName)); } } diff --git a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java b/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java index 665ec7aca7881..f49523c101b77 100644 --- a/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java +++ b/tooling/camel-tooling-maven/src/main/java/org/apache/camel/tooling/maven/MavenDownloaderImpl.java @@ -28,6 +28,7 @@ import java.util.ArrayList; import java.util.Arrays; import java.util.Collections; +import java.util.LinkedHashSet; import java.util.List; import java.util.Set; import java.util.concurrent.atomic.AtomicInteger; @@ -82,6 +83,9 @@ public class MavenDownloaderImpl extends ServiceSupport implements MavenDownload public static final String MAVEN_CENTRAL_REPO = "https://repo1.maven.org/maven2"; public static final String APACHE_SNAPSHOT_REPO = "https://repository.apache.org/snapshots"; + private static final String EXTRA_DEFAULT_REPOS_DEFAULT_VALUE = "camel.default.extra.repos.default.value"; + private static final String EXTRA_DEFAULT_REPOS_PROPERTY = "camel.extra.repos"; + private static final RepositoryPolicy POLICY_DEFAULT = new RepositoryPolicy( true, RepositoryPolicy.UPDATE_POLICY_NEVER, RepositoryPolicy.CHECKSUM_POLICY_WARN); private static final RepositoryPolicy POLICY_FRESH = new RepositoryPolicy( @@ -192,6 +196,9 @@ private void configureRepositoriesForEmbeddedMode() { .build(); } + // Load extra default repositories (classpath properties file + system property) + loadExtraDefaultRepositories(originalRepositories); + // Add custom repositories from repos parameter if (repos != null) { Set urls = Arrays.stream(repos.split("\\s*,\\s*")).collect(Collectors.toSet()); @@ -349,6 +356,9 @@ private void configureMIMA() { .build(); } + // Load extra default repositories (classpath properties file + system property) + loadExtraDefaultRepositories(originalRepositories); + // Add repositories from settings.xml active profiles (provided by MIMA) Set repositoryURLs = originalRepositories.stream() .map(RemoteRepository::getUrl) @@ -490,6 +500,34 @@ private void configureRepositories(List repositories, Set + * Two complementary mechanisms: + *

    + *
  • System property: {@value #EXTRA_DEFAULT_REPOS_PROPERTY or EXTRA_DEFAULT_REPOS_DEFAULT_VALUE} (comma-separated + * id=url pairs)
  • + *
+ * Both are additive and merged. Upstream ships no properties file (no-op). Product builds can add the file or use + * the system property. + */ + private void loadExtraDefaultRepositories(List repositories) { + // Load from system property (comma-separated id=url pairs) + String sysProp + = System.getProperty(EXTRA_DEFAULT_REPOS_PROPERTY, System.getProperty(EXTRA_DEFAULT_REPOS_DEFAULT_VALUE)); + if (sysProp != null && !sysProp.isBlank()) { + Set repoSpecs = Arrays.stream(sysProp.split("\\s*,\\s*")) + .filter(s -> !s.isBlank()) + .collect(Collectors.toCollection(LinkedHashSet::new)); + + if (!repoSpecs.isEmpty()) { + LOG.debug("Loaded extra default repositories from system property: {}", sysProp); + configureRepositories(repositories, repoSpecs); + LOG.debug("Configured {} extra default Maven repositories", repoSpecs.size()); + } + } + } + @Override protected void doInit() { // Nothing to do