diff --git a/src/main/java/dev/jbang/devkitman/JdkDistroQuery.java b/src/main/java/dev/jbang/devkitman/JdkDistroQuery.java new file mode 100644 index 0000000..1594459 --- /dev/null +++ b/src/main/java/dev/jbang/devkitman/JdkDistroQuery.java @@ -0,0 +1,39 @@ +package dev.jbang.devkitman; + +import java.util.List; +import java.util.Objects; + +public interface JdkDistroQuery { + List listDistros(); + + class JdkDistro { + private final String name; + + public JdkDistro(String name) { + this.name = name; + } + + public String name() { + return name; + } + + @Override + public final boolean equals(Object o) { + if (!(o instanceof JdkDistro)) + return false; + + JdkDistro jdkDistro = (JdkDistro) o; + return Objects.equals(name, jdkDistro.name); + } + + @Override + public int hashCode() { + return Objects.hashCode(name); + } + + @Override + public String toString() { + return name; + } + } +} diff --git a/src/main/java/dev/jbang/devkitman/JdkInstaller.java b/src/main/java/dev/jbang/devkitman/JdkInstaller.java index 3216b9d..ae009a4 100644 --- a/src/main/java/dev/jbang/devkitman/JdkInstaller.java +++ b/src/main/java/dev/jbang/devkitman/JdkInstaller.java @@ -11,7 +11,7 @@ * JDKs on the user's system. They should be able to install and uninstall them * at the user's request. */ -public interface JdkInstaller { +public interface JdkInstaller extends JdkDistroQuery { /** * This method returns a set of JDKs that are available for installation. diff --git a/src/main/java/dev/jbang/devkitman/JdkManager.java b/src/main/java/dev/jbang/devkitman/JdkManager.java index 324bacc..ac99117 100644 --- a/src/main/java/dev/jbang/devkitman/JdkManager.java +++ b/src/main/java/dev/jbang/devkitman/JdkManager.java @@ -18,7 +18,7 @@ import dev.jbang.devkitman.jdkproviders.LinkedJdkProvider; import dev.jbang.devkitman.util.JavaUtils; -public class JdkManager { +public class JdkManager implements JdkDistroQuery { public static final int DEFAULT_JAVA_VERSION = 21; public final int defaultJavaVersion; @@ -765,4 +765,12 @@ public boolean isCurrentJdkManaged() { return providers(JdkProvider.Predicates.canUpdate) .anyMatch(p -> p.getInstalledByPath(currentJdk) != null); } + + @Override + public List listDistros() { + return providers(JdkProvider.Predicates.canInstall) + .flatMap(p -> p instanceof JdkDistroQuery ? ((JdkDistroQuery) p).listDistros().stream() : Stream.empty()) + .distinct() + .collect(Collectors.toList()); + } } diff --git a/src/main/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstaller.java b/src/main/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstaller.java index 58f6e4b..571aadb 100644 --- a/src/main/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstaller.java +++ b/src/main/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstaller.java @@ -29,11 +29,12 @@ public class FoojayJdkInstaller implements JdkInstaller { protected final JdkProvider jdkProvider; protected final Function jdkId; protected RemoteAccessProvider remoteAccessProvider; - protected String distro = DEFAULT_DISTRO; + protected String distros = DEFAULT_DISTROS; public static final String FOOJAY_JDK_VERSIONS_URL = "https://api.foojay.io/disco/v3.0/packages?"; + public static final String FOOJAY_JDK_DISTROS_URL = "https://api.foojay.io/disco/v3.0/distributions?include_versions=false&include_synonyms=false"; - public static final String DEFAULT_DISTRO = "temurin,aoj"; + public static final String DEFAULT_DISTROS = "temurin,aoj"; private static final Logger LOGGER = Logger.getLogger(FoojayJdkInstaller.class.getName()); @@ -55,6 +56,15 @@ public static class VersionsResponse { public List result; } + public static class DistroResult { + public String name; + public String api_parameter; + } + + public static class DistrosResponse { + public List result; + } + public FoojayJdkInstaller(@NonNull JdkProvider jdkProvider) { this.jdkProvider = jdkProvider; this.jdkId = jdk -> determineId(jdk) + "-" + jdkProvider.name(); @@ -77,8 +87,8 @@ public FoojayJdkInstaller(@NonNull JdkProvider jdkProvider, @NonNull Function listAvailable() { } private VersionsResponse readPackagesForList() throws IOException { - return readJsonFromUrl( - getVersionsUrl(0, true, OsUtils.getOS(), OsUtils.getArch(), distro, "ga,ea")); + return readVersionsFromUrl( + getVersionsUrl(0, true, OsUtils.getOS(), OsUtils.getArch(), distros, "ga,ea")); } @Override @@ -129,11 +139,11 @@ private VersionsResponse readPackagesForList() throws IOException { } private VersionsResponse readPackagesForVersion(Integer minVersion, boolean openVersion) throws IOException { - VersionsResponse res = readJsonFromUrl( - getVersionsUrl(minVersion, openVersion, OsUtils.getOS(), OsUtils.getArch(), distro, "ga")); + VersionsResponse res = readVersionsFromUrl( + getVersionsUrl(minVersion, openVersion, OsUtils.getOS(), OsUtils.getArch(), distros, "ga")); if (res.result.isEmpty()) { - res = readJsonFromUrl( - getVersionsUrl(minVersion, openVersion, OsUtils.getOS(), OsUtils.getArch(), distro, "ea")); + res = readVersionsFromUrl( + getVersionsUrl(minVersion, openVersion, OsUtils.getOS(), OsUtils.getArch(), distros, "ea")); } return res; } @@ -176,7 +186,7 @@ private Stream processPackages(List jdks, Comparato return tags; } - private VersionsResponse readJsonFromUrl(String url) throws IOException { + private VersionsResponse readVersionsFromUrl(String url) throws IOException { return RemoteAccessProvider.readJsonFromUrl(remoteAccessProvider(), url, VersionsResponse.class); } @@ -209,7 +219,7 @@ private List filterEA(List jdks) { .compare(o1.java_version, o2.java_version); private Comparator majorVersionSort() { - List ds = Arrays.asList(distro.split(",")); + List ds = Arrays.asList(distros.split(",")); Comparator jdkResultDistroComparator = Comparator.comparingInt(o -> ds.indexOf(o.distribution)); return Comparator .comparingInt((JdkResult jdk) -> -jdk.major_version) @@ -256,13 +266,27 @@ public void uninstall(Jdk.@NonNull InstalledJdk jdk) { JavaUtils.safeDeleteJdk(jdk.home()); } + @Override + public List listDistros() { + try { + DistrosResponse response = RemoteAccessProvider.readJsonFromUrl(remoteAccessProvider(), + FOOJAY_JDK_DISTROS_URL, DistrosResponse.class); + return response.result.stream() + .map(d -> new JdkDistro(d.api_parameter)) + .collect(Collectors.toList()); + } catch (IOException e) { + LOGGER.log(Level.FINE, "Couldn't list available JDKs", e); + return Collections.emptyList(); + } + } + private static String getVersionsUrl(int minVersion, boolean openVersion, OsUtils.OS os, OsUtils.Arch arch, - String distro, String status) { - return FOOJAY_JDK_VERSIONS_URL + getUrlParams(minVersion, openVersion, os, arch, distro, status); + String distros, String status) { + return FOOJAY_JDK_VERSIONS_URL + getUrlParams(minVersion, openVersion, os, arch, distros, status); } private static String getUrlParams(int version, boolean openVersion, OsUtils.OS os, OsUtils.Arch arch, - String distro, String status) { + String distros, String status) { Map params = new HashMap<>(); if (version > 0) { String v = String.valueOf(version); @@ -272,14 +296,14 @@ private static String getUrlParams(int version, boolean openVersion, OsUtils.OS params.put("version", v); } - if (distro == null) { + if (distros == null) { if (version == 0 || version == 8 || version == 11 || version >= 17) { - distro = "temurin"; + distros = "temurin"; } else { - distro = "aoj"; + distros = "aoj"; } } - params.put("distro", distro); + params.put("distro", distros); String archiveType; if (os == OsUtils.OS.windows) { @@ -357,7 +381,7 @@ public static class Discovery implements JdkInstallers.Discovery { @Override public @NonNull JdkInstaller create(Config config) { FoojayJdkInstaller installer = new FoojayJdkInstaller(config.jdkProvider()); - installer.distro(config.properties().getOrDefault("distro", null)); + installer.distros(config.properties().getOrDefault("distro", null)); HttpClientBuilder httpClientBuilder = NetUtils.createCachingHttpClientBuilder(config.cachePath()); RemoteAccessProvider rap = RemoteAccessProvider.createDefaultRemoteAccessProvider(httpClientBuilder); installer.remoteAccessProvider(rap); diff --git a/src/main/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstaller.java b/src/main/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstaller.java index 47a9b00..3f73c34 100644 --- a/src/main/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstaller.java +++ b/src/main/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstaller.java @@ -64,6 +64,30 @@ public static class MetadataResult { public Integer size; } + public static final List JDK_DISTROS = Arrays.asList( + new JdkDistro("adoptopenjdk"), + new JdkDistro("bisheng"), + new JdkDistro("corretto"), + new JdkDistro("dragonwell"), + new JdkDistro("graalvm"), + new JdkDistro("graalvm-community"), + new JdkDistro("ibm"), + new JdkDistro("java-se-ri"), + new JdkDistro("jetbrains"), + new JdkDistro("kona"), + new JdkDistro("liberica"), + new JdkDistro("mandrel"), + new JdkDistro("microsoft"), + new JdkDistro("openjdk"), + new JdkDistro("oracle"), + new JdkDistro("oracle-graalvm"), + new JdkDistro("redhat"), + new JdkDistro("sapmachine"), + new JdkDistro("semeru"), + new JdkDistro("temurin"), + new JdkDistro("trava"), + new JdkDistro("zulu")); + public MetadataJdkInstaller(@NonNull JdkProvider jdkProvider) { this.jdkProvider = jdkProvider; this.jdkId = jdk -> determineId(jdk) + "-" + jdkProvider.name(); @@ -332,6 +356,11 @@ public void uninstall(Jdk.@NonNull InstalledJdk jdk) { JavaUtils.safeDeleteJdk(jdk.home()); } + @Override + public List listDistros() { + return JDK_DISTROS; + } + /** * Constructs the metadata API URL for the given parameters Format: * /metadata/{release_type}/{os}/{arch}/{image_type}/{jvm_impl}/{vendor}.json diff --git a/src/main/java/dev/jbang/devkitman/jdkproviders/JBangJdkProvider.java b/src/main/java/dev/jbang/devkitman/jdkproviders/JBangJdkProvider.java index 5d7e359..c8dd5f4 100644 --- a/src/main/java/dev/jbang/devkitman/jdkproviders/JBangJdkProvider.java +++ b/src/main/java/dev/jbang/devkitman/jdkproviders/JBangJdkProvider.java @@ -2,6 +2,7 @@ import java.nio.file.Path; import java.nio.file.Paths; +import java.util.List; import java.util.stream.Stream; import org.jspecify.annotations.NonNull; @@ -9,6 +10,7 @@ import dev.jbang.devkitman.Jdk; import dev.jbang.devkitman.JdkDiscovery; +import dev.jbang.devkitman.JdkDistroQuery; import dev.jbang.devkitman.JdkInstaller; import dev.jbang.devkitman.JdkInstallers; import dev.jbang.devkitman.JdkProvider; @@ -21,7 +23,7 @@ * provided by the Java Metadata API. They get installed in the user's JBang * folder. */ -public class JBangJdkProvider extends BaseFoldersJdkProvider { +public class JBangJdkProvider extends BaseFoldersJdkProvider implements JdkDistroQuery { protected JdkInstaller jdkInstaller; public static final String DEFAULT_INSTALLER = "foojay"; @@ -71,6 +73,11 @@ public void uninstall(Jdk.@NonNull InstalledJdk jdk) { jdkInstaller.uninstall(jdk); } + @Override + public List listDistros() { + return jdkInstaller.listDistros(); + } + @Override public boolean canUpdate() { return true; diff --git a/src/main/java/dev/jbang/devkitman/util/RemoteAccessProvider.java b/src/main/java/dev/jbang/devkitman/util/RemoteAccessProvider.java index a2c55ad..3d2f628 100644 --- a/src/main/java/dev/jbang/devkitman/util/RemoteAccessProvider.java +++ b/src/main/java/dev/jbang/devkitman/util/RemoteAccessProvider.java @@ -10,6 +10,7 @@ import com.google.gson.Gson; import com.google.gson.GsonBuilder; +import com.google.gson.Strictness; public interface RemoteAccessProvider { @@ -26,7 +27,7 @@ default T resultFromUrl(String url, FunctionWithError stream static T readJsonFromUrl(RemoteAccessProvider rap, String url, Class klass) throws IOException { return rap.resultFromUrl(url, is -> { try (InputStream ignored = is) { - Gson parser = new GsonBuilder().create(); + Gson parser = new GsonBuilder().setStrictness(Strictness.LENIENT).create(); return parser.fromJson(new InputStreamReader(is), klass); } catch (IOException e) { throw new RuntimeException(e); diff --git a/src/test/java/dev/jbang/devkitman/BaseTest.java b/src/test/java/dev/jbang/devkitman/BaseTest.java index 2e9b657..c32519f 100644 --- a/src/test/java/dev/jbang/devkitman/BaseTest.java +++ b/src/test/java/dev/jbang/devkitman/BaseTest.java @@ -226,6 +226,9 @@ public T resultFromUrl( if (url.startsWith(FoojayJdkInstaller.FOOJAY_JDK_VERSIONS_URL)) { return streamToObject.apply( getClass().getResourceAsStream("/testFoojayInstall.json")); + } else if (url.startsWith(FoojayJdkInstaller.FOOJAY_JDK_DISTROS_URL)) { + return streamToObject.apply( + getClass().getResourceAsStream("/testFoojayDistros.json")); } else if (url.startsWith(MetadataJdkInstaller.METADATA_BASE_URL)) { return streamToObject.apply( getClass().getResourceAsStream("/testMetadataInstall.json")); @@ -236,7 +239,7 @@ public T resultFromUrl( JBangJdkProvider jbang = new JBangJdkProvider(config.installPath()); FoojayJdkInstaller installer = new FoojayJdkInstaller(jbang) - .distro("jbang") + .distros("jbang") .remoteAccessProvider(rap); installer.remoteAccessProvider(rap); jbang.installer(installer); diff --git a/src/test/java/dev/jbang/devkitman/TestJdkManager.java b/src/test/java/dev/jbang/devkitman/TestJdkManager.java index 5b68e76..f747d02 100644 --- a/src/test/java/dev/jbang/devkitman/TestJdkManager.java +++ b/src/test/java/dev/jbang/devkitman/TestJdkManager.java @@ -487,4 +487,13 @@ void testUninstallAll() { jdks = jm.listInstalledJdks(); assertThat(jdks, empty()); } + + @Test + public void testListDistros() { + JdkManager jm = jdkManager(); + List distros = jm.listDistros(); + assertThat(distros.size(), equalTo(30)); + assertThat(distros.toString(), equalTo( + "[zulu, trava, temurin, semeru_certified, semeru, sap_machine, redhat, oracle_open_jdk, oracle, openlogic, ojdk_build, microsoft, mandrel, liberica_native, liberica, kona, jetbrains, graalvm_community, graalvm_ce8, graalvm_ce19, graalvm_ce17, graalvm_ce16, graalvm_ce11, graalvm, gluon_graalvm, dragonwell, corretto, bisheng, aoj_openj9, aoj]")); + } } diff --git a/src/test/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstallerTest.java b/src/test/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstallerTest.java index 3c2c6bc..083ddf3 100644 --- a/src/test/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstallerTest.java +++ b/src/test/java/dev/jbang/devkitman/jdkinstallers/FoojayJdkInstallerTest.java @@ -18,6 +18,7 @@ import dev.jbang.devkitman.BaseTest; import dev.jbang.devkitman.Jdk; +import dev.jbang.devkitman.JdkDistroQuery; import dev.jbang.devkitman.JdkManager; import dev.jbang.devkitman.jdkproviders.JBangJdkProvider; import dev.jbang.devkitman.util.FunctionWithError; @@ -44,7 +45,7 @@ protected void initEnv(@TempDir Path tempPath) throws IOException { RemoteAccessProvider rap = createRemoteAccessProvider(); provider = new JBangJdkProvider(config.installPath()); installer = new FoojayJdkInstaller(provider) - .distro("jbang") + .distros("jbang") .remoteAccessProvider(rap); provider.installer(installer); @@ -69,12 +70,16 @@ public Path downloadFromUrl(String url) throws IOException { public T resultFromUrl(String url, FunctionWithError streamToObject) throws IOException { // Verify the URL format matches expected Foojay API pattern - if (!url.startsWith(FoojayJdkInstaller.FOOJAY_JDK_VERSIONS_URL)) { - throw new IOException("Unexpected URL: " + url); + if (url.startsWith(FoojayJdkInstaller.FOOJAY_JDK_VERSIONS_URL)) { + // Return our test Foojay JSON for all requests + return streamToObject.apply( + getClass().getResourceAsStream("/testFoojayInstall.json")); + } else if (url.startsWith(FoojayJdkInstaller.FOOJAY_JDK_DISTROS_URL)) { + // Return our test Foojay JSON for all requests + return streamToObject.apply( + getClass().getResourceAsStream("/testFoojayDistros.json")); } - // Return our test Foojay JSON for all requests - return streamToObject.apply( - getClass().getResourceAsStream("/testFoojayInstall.json")); + throw new IOException("Unexpected URL: " + url); } }; } @@ -141,7 +146,7 @@ public void testGetAvailableByVersionNotFound() { } @Test - public void testDetermineIdIncludesDistro() { + public void testDetermineIdIncludesDistros() { List jdks = installer.listAvailable().collect(Collectors.toList()); assertThat(jdks, is(not(empty()))); @@ -300,7 +305,7 @@ public void testAvailableFoojayJdkCreation() { } @Test - public void testDistroSortingOrder() { + public void testDistrosSortingOrder() { // Test that JDKs are sorted by distribution preference List jdks = installer.listAvailable().collect(Collectors.toList()); @@ -346,4 +351,13 @@ public void testMajorVersionExtraction() { assertThat(major, allOf(greaterThanOrEqualTo(8), lessThanOrEqualTo(30))); } } + + @Test + public void testListDistros() { + List distros = installer.listDistros(); + assertThat(distros.size(), equalTo(30)); + assertThat(distros.toString(), equalTo( + "[zulu, trava, temurin, semeru_certified, semeru, sap_machine, redhat, oracle_open_jdk, oracle, openlogic, ojdk_build, microsoft, mandrel, liberica_native, liberica, kona, jetbrains, graalvm_community, graalvm_ce8, graalvm_ce19, graalvm_ce17, graalvm_ce16, graalvm_ce11, graalvm, gluon_graalvm, dragonwell, corretto, bisheng, aoj_openj9, aoj]")); + } + } diff --git a/src/test/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstallerTest.java b/src/test/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstallerTest.java index 9c8e440..08b425c 100644 --- a/src/test/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstallerTest.java +++ b/src/test/java/dev/jbang/devkitman/jdkinstallers/MetadataJdkInstallerTest.java @@ -18,6 +18,7 @@ import dev.jbang.devkitman.BaseTest; import dev.jbang.devkitman.Jdk; +import dev.jbang.devkitman.JdkDistroQuery; import dev.jbang.devkitman.JdkManager; import dev.jbang.devkitman.jdkproviders.JBangJdkProvider; import dev.jbang.devkitman.util.FunctionWithError; @@ -291,4 +292,12 @@ public void testAvailableMetadataJdkCreation() { assertThat(jdk.provider(), is(provider)); } } + + @Test + public void testListDistros() { + List distros = installer.listDistros(); + assertThat(distros.size(), equalTo(22)); + assertThat(distros.toString(), equalTo( + "[adoptopenjdk, bisheng, corretto, dragonwell, graalvm, graalvm-community, ibm, java-se-ri, jetbrains, kona, liberica, mandrel, microsoft, openjdk, oracle, oracle-graalvm, redhat, sapmachine, semeru, temurin, trava, zulu]")); + } } diff --git a/src/test/resources/testFoojayDistros.json b/src/test/resources/testFoojayDistros.json new file mode 100644 index 0000000..b41b080 --- /dev/null +++ b/src/test/resources/testFoojayDistros.json @@ -0,0 +1,305 @@ +{ + "result": [ + { + "name": "Zulu", + "api_parameter": "zulu", + "vendor": "azul", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://www.azul.com/downloads/?package=jdk" + }, + { + "name": "Trava", + "api_parameter": "trava", + "vendor": "community", + "maintained": false, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://github.com/TravaOpenJDK" + }, + { + "name": "Temurin", + "api_parameter": "temurin", + "vendor": "eclipse_foundation", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://adoptium.net/temurin/releases" + }, + { + "name": "Semeru certified", + "api_parameter": "semeru_certified", + "vendor": "ibm", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://developer.ibm.com/languages/java/semeru-runtimes/" + }, + { + "name": "Semeru", + "api_parameter": "semeru", + "vendor": "ibm", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://developer.ibm.com/languages/java/semeru-runtimes/" + }, + { + "name": "SAP Machine", + "api_parameter": "sap_machine", + "vendor": "sap", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://sapmachine.io" + }, + { + "name": "Red Hat", + "api_parameter": "redhat", + "vendor": "red_hat", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://developers.redhat.com/products/openjdk/overview" + }, + { + "name": "Oracle OpenJDK", + "api_parameter": "oracle_open_jdk", + "vendor": "oracle", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://openjdk.org/" + }, + { + "name": "Oracle", + "api_parameter": "oracle", + "vendor": "oracle", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://www.oracle.com/java/" + }, + { + "name": "OpenLogic", + "api_parameter": "openlogic", + "vendor": "open_logic", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://www.openlogic.com" + }, + { + "name": "OJDKBuild", + "api_parameter": "ojdk_build", + "vendor": "community", + "maintained": false, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://github.com/ojdkbuild/ojdkbuild" + }, + { + "name": "Microsoft", + "api_parameter": "microsoft", + "vendor": "microsoft", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://www.microsoft.com/openjdk" + }, + { + "name": "Mandrel", + "api_parameter": "mandrel", + "vendor": "red_hat", + "maintained": true, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://developers.redhat.com/blog/2021/04/14/mandrel-a-specialized-distribution-of-graalvm-for-quarkus#" + }, + { + "name": "Liberica Native", + "api_parameter": "liberica_native", + "vendor": "bell_soft", + "maintained": true, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://bell-sw.com/" + }, + { + "name": "Liberica", + "api_parameter": "liberica", + "vendor": "bell_soft", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://bell-sw.com/" + }, + { + "name": "Kona", + "api_parameter": "kona", + "vendor": "tencent", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://tencent.github.io/konajdk" + }, + { + "name": "JetBrains", + "api_parameter": "jetbrains", + "vendor": "jetbrains", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://github.com/JetBrains/JetBrainsRuntime" + }, + { + "name": "GraalVM Community", + "api_parameter": "graalvm_community", + "vendor": "oracle", + "maintained": true, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://www.graalvm.org/" + }, + { + "name": "GraalVM CE 8", + "api_parameter": "graalvm_ce8", + "vendor": "oracle", + "maintained": false, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://www.graalvm.org/" + }, + { + "name": "GraalVM CE 19", + "api_parameter": "graalvm_ce19", + "vendor": "oracle", + "maintained": false, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://www.graalvm.org/" + }, + { + "name": "GraalVM CE 17", + "api_parameter": "graalvm_ce17", + "vendor": "oracle", + "maintained": false, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://www.graalvm.org/" + }, + { + "name": "GraalVM CE 16", + "api_parameter": "graalvm_ce16", + "vendor": "oracle", + "maintained": false, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://www.graalvm.org/" + }, + { + "name": "GraalVM CE 11", + "api_parameter": "graalvm_ce11", + "vendor": "oracle", + "maintained": false, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://www.graalvm.org/" + }, + { + "name": "GraalVM", + "api_parameter": "graalvm", + "vendor": "oracle", + "maintained": true, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://www.graalvm.org/" + }, + { + "name": "Gluon GraalVM", + "api_parameter": "gluon_graalvm", + "vendor": "gluon", + "maintained": true, + "available": true, + "build_of_openjdk": false, + "build_of_graalvm": true, + "official_uri": "https://docs.gluonhq.com/#_graalvm" + }, + { + "name": "Dragonwell", + "api_parameter": "dragonwell", + "vendor": "alibaba", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "http://dragonwell-jdk.io/" + }, + { + "name": "Corretto", + "api_parameter": "corretto", + "vendor": "amazon", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://aws.amazon.com/de/corretto/" + }, + { + "name": "Bi Sheng", + "api_parameter": "bisheng", + "vendor": "huawei", + "maintained": true, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://www.hikunpeng.com/en/developer/devkit/compiler?data=JDK" + }, + { + "name": "AOJ OpenJ9", + "api_parameter": "aoj_openj9", + "vendor": "adopt_open_jdk", + "maintained": false, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://adoptopenjdk.net/" + }, + { + "name": "AOJ", + "api_parameter": "aoj", + "vendor": "adopt_open_jdk", + "maintained": false, + "available": true, + "build_of_openjdk": true, + "build_of_graalvm": false, + "official_uri": "https://adoptopenjdk.net/" + } + ], + "message": "" +} \ No newline at end of file