Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -35,6 +35,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;
Expand Down Expand Up @@ -144,6 +145,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<String> deps = resolveDependencies(settings, profile);
// copy local lib JARs
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,59 @@ public static <T> void resolveQuarkusPlatformVersions(
Function<T, String> runtimeVersionFunc,
BiConsumer<T, String> quarkusVersionSetter) {

JsonArray streams = fetchPlatformStreams();
if (streams == null) {
return;
}

// keep the row with the highest runtime version per major.minor stream
BinaryOperator<T> keepLatest = (a, b) -> VersionHelper.compare(
runtimeVersionFunc.apply(a), runtimeVersionFunc.apply(b)) >= 0 ? a : b;

Map<String, T> 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.
* <p>
* 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<String> 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<String> res = hc.send(
Expand All @@ -80,45 +133,33 @@ public static <T> 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<T> keepLatest = (a, b) -> VersionHelper.compare(
runtimeVersionFunc.apply(a), runtimeVersionFunc.apply(b)) >= 0 ? a : b;

Map<String, T> 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<String> findQuarkusCoreVersion(JsonArray streams, String majorMinor) {
private static Optional<String> findStreamVersion(JsonArray streams, String majorMinor, String fieldName) {
return streams.stream()
.map(s -> (JsonObject) s)
.filter(stream -> majorMinor.equals(stream.getString("id")))
.findFirst()
.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));
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.LinkedHashSet;
import java.util.List;
import java.util.Map;
import java.util.Objects;
Expand Down Expand Up @@ -230,6 +231,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(
Expand Down Expand Up @@ -353,6 +357,37 @@ protected void doBuild() {
apacheSnapshotsResolutionRepository = repositorySystem.newResolutionRepositories(repositorySystemSession,
Collections.singletonList(apacheSnapshotsRepository)).get(0);
}

// Load extra default repositories (classpath properties file + system property)
loadExtraDefaultRepositories(originalRepositories);
}

/**
* Loads extra default Maven repositories from classpath properties files and system property.
* <p>
* Two complementary mechanisms:
* <ul>
* <li>System property: {@value #EXTRA_DEFAULT_REPOS_PROPERTY or EXTRA_DEFAULT_REPOS_DEFAULT_VALUE} (comma-separated
* id=url pairs)</li>
* </ul>
* 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<RemoteRepository> 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<String> 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
Expand Down
Loading