summaryrefslogtreecommitdiff
path: root/meta
diff options
context:
space:
mode:
authorSefa Eyeoglu <contact@scrumplex.net>2024-06-14 16:59:45 +0200
committerGitHub <noreply@github.com>2024-06-14 16:59:45 +0200
commit395ca19ee418d535158904f2639f5b4fbe574b52 (patch)
tree4ecc30f3aa0fe8d9b79483a823b1a178a3fa618b /meta
parenta4f59d327a02338b8342d83931758e6a17a85e00 (diff)
parent6706cb5258e023bdada0cb4de0291bc96e113132 (diff)
downloadProject-Tick-395ca19ee418d535158904f2639f5b4fbe574b52.tar.gz
Project-Tick-395ca19ee418d535158904f2639f5b4fbe574b52.zip
Merge pull request #19 from Ryex/javas
Add java runtime metadata
Diffstat (limited to 'meta')
-rw-r--r--meta/common/__init__.py15
-rw-r--r--meta/common/java.py14
-rw-r--r--meta/common/mojang.py2
-rw-r--r--meta/model/__init__.py38
-rw-r--r--meta/model/enum.py32
-rw-r--r--meta/model/java.py558
-rw-r--r--meta/model/mojang.py72
-rw-r--r--meta/run/generate_java.py481
-rw-r--r--meta/run/update_java.py158
-rwxr-xr-xmeta/run/update_mojang.py19
10 files changed, 1364 insertions, 25 deletions
diff --git a/meta/common/__init__.py b/meta/common/__init__.py
index 9e623bdca8..d7ee49ac4a 100644
--- a/meta/common/__init__.py
+++ b/meta/common/__init__.py
@@ -2,10 +2,11 @@ import os
import os.path
import datetime
from urllib.parse import urlparse
+from typing import Any, Optional
import requests
-from cachecontrol import CacheControl
-from cachecontrol.caches import FileCache
+from cachecontrol import CacheControl # type: ignore
+from cachecontrol.caches import FileCache # type: ignore
LAUNCHER_MAVEN = "https://files.prismlauncher.org/maven/%s"
@@ -41,7 +42,7 @@ def ensure_upstream_dir(path):
os.makedirs(path)
-def ensure_component_dir(component_id):
+def ensure_component_dir(component_id: str):
path = os.path.join(launcher_path(), component_id)
if not os.path.exists(path):
os.makedirs(path)
@@ -51,7 +52,7 @@ def transform_maven_key(maven_key: str):
return maven_key.replace(":", ".")
-def replace_old_launchermeta_url(url):
+def replace_old_launchermeta_url(url: str):
o = urlparse(url)
if o.netloc == "launchermeta.mojang.com":
return o._replace(netloc="piston-meta.mojang.com").geturl()
@@ -59,7 +60,7 @@ def replace_old_launchermeta_url(url):
return url
-def get_all_bases(cls, bases=None):
+def get_all_bases(cls: type, bases: Optional[list[type]] = None):
bases = bases or []
bases.append(cls)
for c in cls.__bases__:
@@ -67,10 +68,10 @@ def get_all_bases(cls, bases=None):
return tuple(bases)
-def merge_dict(base: dict, overlay: dict):
+def merge_dict(base: dict[Any, Any], overlay: dict[Any, Any]):
for k, v in base.items():
if isinstance(v, dict):
- merge_dict(v, overlay.setdefault(k, {}))
+ merge_dict(v, overlay.setdefault(k, {})) # type: ignore
else:
if k not in overlay:
overlay[k] = v
diff --git a/meta/common/java.py b/meta/common/java.py
new file mode 100644
index 0000000000..ec13b2a55f
--- /dev/null
+++ b/meta/common/java.py
@@ -0,0 +1,14 @@
+from os.path import join
+
+BASE_DIR = "java_runtime"
+
+RELEASE_FILE = join(BASE_DIR, "releases.json")
+ADOPTIUM_DIR = join(BASE_DIR, "adoptium")
+AZUL_DIR = join(BASE_DIR, "azul")
+
+ADOPTIUM_VERSIONS_DIR = join(ADOPTIUM_DIR, "versions")
+AZUL_VERSIONS_DIR = join(AZUL_DIR, "versions")
+
+JAVA_MINECRAFT_COMPONENT = "net.minecraft.java"
+JAVA_ADOPTIUM_COMPONENT = "net.adoptium.java"
+JAVA_AZUL_COMPONENT = "com.azul.java"
diff --git a/meta/common/mojang.py b/meta/common/mojang.py
index 5fda2e002f..fe36c3c02b 100644
--- a/meta/common/mojang.py
+++ b/meta/common/mojang.py
@@ -19,3 +19,5 @@ LIBRARY_PATCHES_FILE = join(dirname(__file__), "mojang-library-patches.json")
MINECRAFT_COMPONENT = "net.minecraft"
LWJGL_COMPONENT = "org.lwjgl"
LWJGL3_COMPONENT = "org.lwjgl3"
+
+JAVA_MANIFEST_FILE = join(BASE_DIR, "java_all.json")
diff --git a/meta/model/__init__.py b/meta/model/__init__.py
index fb062f5d35..3d06f998ab 100644
--- a/meta/model/__init__.py
+++ b/meta/model/__init__.py
@@ -4,7 +4,7 @@ from pathlib import Path
from typing import Optional, List, Dict, Any, Iterator
import pydantic
-from pydantic import Field, validator
+from pydantic import Field, validator # type: ignore
from ..common import (
LAUNCHER_MAVEN,
@@ -87,13 +87,16 @@ class GradleSpecifier:
def is_log4j(self):
return self.group == "org.apache.logging.log4j"
- def __eq__(self, other):
- return str(self) == str(other)
+ def __eq__(self, other: Any):
+ if isinstance(other, GradleSpecifier):
+ return str(self) == str(other)
+ else:
+ return False
- def __lt__(self, other):
+ def __lt__(self, other: "GradleSpecifier"):
return str(self) < str(other)
- def __gt__(self, other):
+ def __gt__(self, other: "GradleSpecifier"):
return str(self) > str(other)
def __hash__(self):
@@ -122,7 +125,7 @@ class GradleSpecifier:
return cls(group, artifact, version, classifier, extension)
@classmethod
- def validate(cls, v):
+ def validate(cls, v: "str | GradleSpecifier"):
if isinstance(v, cls):
return v
if isinstance(v, str):
@@ -131,7 +134,7 @@ class GradleSpecifier:
class MetaBase(pydantic.BaseModel):
- def dict(self, **kwargs) -> Dict[str, Any]:
+ def dict(self, **kwargs: Any) -> Dict[str, Any]:
for k in ["by_alias"]:
if k in kwargs:
del kwargs[k]
@@ -147,12 +150,12 @@ class MetaBase(pydantic.BaseModel):
exclude_none=True, sort_keys=True, by_alias=True, indent=4, **kwargs
)
- def write(self, file_path):
+ def write(self, file_path: str):
Path(file_path).parent.mkdir(parents=True, exist_ok=True)
with open(file_path, "w") as f:
f.write(self.json())
- def merge(self, other):
+ def merge(self, other: "MetaBase"):
"""
Merge other object with self.
- Concatenates lists
@@ -176,14 +179,14 @@ class MetaBase(pydantic.BaseModel):
elif isinstance(ours, set):
ours |= theirs
elif isinstance(ours, dict):
- result = merge_dict(ours, copy.deepcopy(theirs))
+ result = merge_dict(ours, copy.deepcopy(theirs)) # type: ignore
setattr(self, key, result)
elif MetaBase in get_all_bases(field.type_):
ours.merge(theirs)
else:
setattr(self, key, theirs)
- def __hash__(self):
+ def __hash__(self): # type: ignore
return hash(self.json())
class Config:
@@ -194,7 +197,7 @@ class MetaBase(pydantic.BaseModel):
class Versioned(MetaBase):
@validator("format_version")
- def format_version_must_be_supported(cls, v):
+ def format_version_must_be_supported(cls, v: int):
assert v <= META_FORMAT_VERSION
return v
@@ -209,7 +212,7 @@ class MojangArtifactBase(MetaBase):
class MojangAssets(MojangArtifactBase):
@validator("url")
- def validate_url(cls, v):
+ def validate_url(cls, v: str):
return replace_old_launchermeta_url(v)
id: str
@@ -245,7 +248,7 @@ class MojangLibraryDownloads(MetaBase):
class OSRule(MetaBase):
@validator("name")
- def name_must_be_os(cls, v):
+ def name_must_be_os(cls, v: str):
assert v in [
"osx",
"linux",
@@ -263,7 +266,7 @@ class OSRule(MetaBase):
class MojangRule(MetaBase):
@validator("action")
- def action_must_be_allow_disallow(cls, v):
+ def action_must_be_allow_disallow(cls, v: str):
assert v in ["allow", "disallow"]
return v
@@ -274,10 +277,10 @@ class MojangRule(MetaBase):
class MojangRules(MetaBase):
__root__: List[MojangRule]
- def __iter__(self) -> Iterator[MojangRule]:
+ def __iter__(self) -> Iterator[MojangRule]: # type: ignore
return iter(self.__root__)
- def __getitem__(self, item) -> MojangRule:
+ def __getitem__(self, item: int) -> MojangRule:
return self.__root__[item]
@@ -316,6 +319,7 @@ class MetaVersion(Versioned):
minecraft_arguments: Optional[str] = Field(alias="minecraftArguments")
release_time: Optional[datetime] = Field(alias="releaseTime")
compatible_java_majors: Optional[List[int]] = Field(alias="compatibleJavaMajors")
+ compatible_java_name: Optional[str] = Field(alias="compatibleJavaName")
additional_traits: Optional[List[str]] = Field(alias="+traits")
additional_tweakers: Optional[List[str]] = Field(alias="+tweakers")
additional_jvm_args: Optional[List[str]] = Field(alias="+jvmArgs")
diff --git a/meta/model/enum.py b/meta/model/enum.py
new file mode 100644
index 0000000000..08dda4bf4a
--- /dev/null
+++ b/meta/model/enum.py
@@ -0,0 +1,32 @@
+import enum
+
+
+class StrEnum(str, enum.Enum):
+ """
+ StrEnum is a Python ``enum.Enum`` that inherits from ``str``. The default
+ ``auto()`` behavior uses the member name as its value.
+
+ Example usage::
+
+ class Example(StrEnum):
+ UPPER_CASE = auto()
+ lower_case = auto()
+ MixedCase = auto()
+
+ assert Example.UPPER_CASE == "UPPER_CASE"
+ assert Example.lower_case == "lower_case"
+ assert Example.MixedCase == "MixedCase"
+ """
+
+ def __new__(cls, value, *args, **kwargs):
+ if not isinstance(value, (str, enum.auto)):
+ raise TypeError(
+ f"Values of StrEnums must be strings: {value!r} is a {type(value)}"
+ )
+ return super().__new__(cls, value, *args, **kwargs)
+
+ def __str__(self):
+ return str(self.value)
+
+ def _generate_next_value_(name, *_):
+ return name
diff --git a/meta/model/java.py b/meta/model/java.py
new file mode 100644
index 0000000000..e24932ef85
--- /dev/null
+++ b/meta/model/java.py
@@ -0,0 +1,558 @@
+from . import (
+ MetaBase,
+ MetaVersion,
+ Versioned,
+)
+from pydantic import Field
+from datetime import datetime
+from enum import IntEnum, Enum
+from .enum import StrEnum
+from typing import Optional, Any, NamedTuple, Generator
+from urllib.parse import urlencode, urlparse, urlunparse
+from functools import total_ordering
+
+# namedtuple to match the internal signature of urlunparse
+
+
+class JavaRuntimeOS(StrEnum):
+ MacOsX64 = "mac-os-x64"
+ MacOsX86 = "mac-os-x86" # rare
+ MacOsArm64 = "mac-os-arm64"
+ # MacOsArm32 = "mac-os-arm32" # doesn't exsist
+ LinuxX64 = "linux-x64"
+ LinuxX86 = "linux-x86"
+ LinuxArm64 = "linux-arm64"
+ LinuxArm32 = "linux-arm32"
+ WindowsX64 = "windows-x64"
+ WindowsX86 = "windows-x86"
+ WindowsArm64 = "windows-arm64"
+ WindowsArm32 = "windows-arm32"
+ Unknown = "unknown"
+
+
+class JavaRuntimeDownloadType(StrEnum):
+ Manifest = "manifest"
+ Archive = "archive"
+
+
+@total_ordering
+class JavaVersionMeta(MetaBase):
+ major: int
+ minor: int
+ security: int
+ build: Optional[int] = None
+ name: Optional[str] = None
+
+ def __str__(self):
+ ver = f"{self.major}.{self.minor}.{self.security}"
+ if self.build is not None:
+ ver = f"{ver}+{self.build}"
+ return ver
+
+ def to_tuple(self):
+ build = 0
+ if self.build is not None:
+ build = self.build
+ return (self.major, self.minor, self.security, build)
+
+ def __eq__(self, other: Any):
+ return self.to_tuple() == other.to_tuple()
+
+ def __lt__(self, other: "JavaVersionMeta"):
+ return self.to_tuple() < other.to_tuple()
+
+
+class JavaChecksumType(StrEnum):
+ Sha1 = "sha1"
+ Sha256 = "sha256"
+
+
+class JavaChecksumMeta(MetaBase):
+ type: JavaChecksumType
+ hash: str
+
+
+class JavaPackageType(StrEnum):
+ Jre = "jre"
+ Jdk = "jdk"
+
+
+class JavaRuntimeMeta(MetaBase):
+ name: str
+ vendor: str
+ url: str
+ release_time: datetime = Field(alias="releaseTime")
+ checksum: Optional[JavaChecksumMeta]
+ download_type: JavaRuntimeDownloadType = Field(alias="downloadType")
+ package_type: JavaPackageType = Field(alias="packageType")
+ version: JavaVersionMeta
+ runtime_os: JavaRuntimeOS = Field(alias="runtimeOS")
+
+
+class JavaRuntimeVersion(MetaVersion):
+ runtimes: list[JavaRuntimeMeta]
+
+
+class URLComponents(NamedTuple):
+ scheme: str
+ netloc: str
+ url: str
+ path: str
+ query: str
+ fragment: str
+
+
+class APIQuery(MetaBase):
+ def to_query(self):
+ set_parts: dict[str, Any] = {}
+ for key, value in self.dict().items():
+ if value is not None:
+ if isinstance(value, Enum):
+ set_parts[key] = value.value
+ elif isinstance(value, list):
+ if len(value) > 0: # type: ignore
+ set_parts[key] = value
+ elif isinstance(value, datetime):
+ set_parts[key] = value.isoformat()
+ else:
+ set_parts[key] = value
+ return urlencode(set_parts, doseq=True)
+
+
+class AdoptiumJvmImpl(StrEnum):
+ Hostspot = "hotspot"
+
+
+class AdoptiumVendor(StrEnum):
+ Eclipse = "eclipse"
+
+
+class AdoptiumArchitecture(StrEnum):
+ X64 = "x64"
+ X86 = "x86"
+ X32 = "x32"
+ Ppc64 = "ppc64"
+ Ppc64le = "ppc64le"
+ S390x = "s390x"
+ Aarch64 = "aarch64"
+ Arm = "arm"
+ Sparcv9 = "sparcv9"
+ Riscv64 = "riscv64"
+
+
+class AdoptiumReleaseType(StrEnum):
+ GenralAccess = "ga"
+ EarlyAccess = "ea"
+
+
+class AdoptiumSortMethod(StrEnum):
+ Default = "DEFAULT"
+ Date = "DATE"
+
+
+class AdoptiumSortOrder(StrEnum):
+ Asc = "ASC"
+ Desc = "DESC"
+
+
+class AdoptiumImageType(StrEnum):
+ Jdk = "jdk"
+ Jre = "jre"
+ Testimage = "testimage"
+ Debugimage = "debugimage"
+ Staticlibs = "staticlibs"
+ Sources = "sources"
+ Sbom = "sbom"
+
+
+class AdoptiumHeapSize(StrEnum):
+ Normal = "normal"
+ Large = "large"
+
+
+class AdoptiumProject(StrEnum):
+ Jdk = "jdk"
+ Valhalla = "valhalla"
+ Metropolis = "metropolis"
+ Jfr = "jfr"
+ Shenandoah = "shenandoah"
+
+
+class AdoptiumCLib(StrEnum):
+ Musl = "musl"
+ Glibc = "glibc"
+
+
+class AdoptiumOs(StrEnum):
+ Linux = "linux"
+ Windows = "windows"
+ Mac = "mac"
+ Solaris = "solaris"
+ Aix = "aix"
+ AlpineLinux = "alpine-linux"
+
+
+ADOPTIUM_API_BASE = " https://api.adoptium.net"
+ADOPTIUM_API_FEATURE_RELEASES = f"{ADOPTIUM_API_BASE}/v3/assets/feature_releases/{{feature_version}}/{{release_type}}"
+# ?image_type={{image_type}}&heap_size={{heap_size}}&project={{project}}&vendor={{vendor}}&page_size={{page_size}}&page={{page}}&sort_method={{sort_method}}&sort_order={{sort_order}}
+ADOPTIUM_API_AVAILABLE_RELEASES = f"{ADOPTIUM_API_BASE}/v3/info/available_releases"
+
+
+class AdoptiumAPIFeatureReleasesQuery(APIQuery):
+ architecture: Optional[AdoptiumArchitecture] = None
+ before: Optional[datetime] = None
+ c_lib: Optional[AdoptiumCLib] = None
+ heap_size: Optional[AdoptiumHeapSize] = AdoptiumHeapSize.Normal
+ image_type: Optional[AdoptiumImageType] = None
+ jvm_impl: Optional[AdoptiumJvmImpl] = None
+ os: Optional[AdoptiumOs] = None
+ page_size: int = 10
+ page: int = 0
+ project: Optional[AdoptiumProject] = AdoptiumProject.Jdk
+ sort_method: Optional[AdoptiumSortMethod] = AdoptiumSortMethod.Default
+ sort_order: Optional[AdoptiumSortOrder] = AdoptiumSortOrder.Desc
+ vendor: Optional[AdoptiumVendor] = AdoptiumVendor.Eclipse
+
+
+def adoptiumAPIFeatureReleasesUrl(
+ feature: int,
+ release_type: AdoptiumReleaseType = AdoptiumReleaseType.GenralAccess,
+ query: AdoptiumAPIFeatureReleasesQuery = AdoptiumAPIFeatureReleasesQuery(),
+):
+ url = urlparse(
+ ADOPTIUM_API_FEATURE_RELEASES.format(
+ feature_version=feature,
+ release_type=release_type.value,
+ )
+ )
+ return urlunparse(url._replace(query=query.to_query()))
+
+
+class AdoptiumAvailableReleases(MetaBase):
+ available_releases: list[int]
+ available_lts_releases: list[int]
+ most_recent_lts: Optional[int]
+ most_recent_feature_release: Optional[int]
+ most_recent_feature_version: Optional[int]
+ tip_version: Optional[int]
+
+
+class AdoptiumFile(MetaBase):
+ name: str
+ link: str
+ size: Optional[int]
+
+
+class AdoptiumPackage(AdoptiumFile):
+ checksum: Optional[str]
+ checksum_link: Optional[str]
+ signature_link: Optional[str]
+ download_count: Optional[int]
+ metadata_link: Optional[str]
+
+
+class AdoptiumBinary(MetaBase):
+ os: str
+ architecture: AdoptiumArchitecture
+ image_type: AdoptiumImageType
+ c_lib: Optional[AdoptiumCLib]
+ jvm_impl: AdoptiumJvmImpl
+ package: Optional[AdoptiumPackage]
+ installer: Optional[AdoptiumPackage]
+ heap_size: AdoptiumHeapSize
+ download_count: Optional[int]
+ updated_at: datetime
+ scm_ref: Optional[str]
+ project: AdoptiumProject
+
+
+class AdoptiumVersion(MetaBase):
+ major: Optional[int]
+ minor: Optional[int]
+ security: Optional[int]
+ patch: Optional[int]
+ pre: Optional[str]
+ adopt_build_number: Optional[int]
+ semver: str
+ openjdk_version: str
+ build: Optional[int]
+ optional: Optional[str]
+
+
+class AdoptiumRelease(MetaBase):
+ release_id: str = Field(alias="id")
+ release_link: str
+ release_name: str
+ timestamp: datetime
+ updated_at: datetime
+ binaries: list[AdoptiumBinary]
+ download_count: Optional[int]
+ release_type: str
+ vendor: AdoptiumVendor
+ version_data: AdoptiumVersion
+ source: Optional[AdoptiumFile]
+ release_notes: Optional[AdoptiumFile]
+
+
+class AdoptiumReleases(MetaBase):
+ __root__: list[AdoptiumRelease]
+
+ def __iter__(self) -> Generator[tuple[str, AdoptiumRelease], None, None]:
+ yield from ((str(i), val) for i, val in enumerate(self.__root__))
+
+ def __getitem__(self, item: int) -> AdoptiumRelease:
+ return self.__root__[item]
+
+ def append(self, rls: AdoptiumRelease):
+ self.__root__.append(rls)
+
+
+class AzulProduct(StrEnum):
+ Zulu = "zulu"
+
+
+class AzulAvailabilityType(StrEnum):
+ SA = "SA"
+ CA = "CA"
+ NV = "NV"
+ _LA = "LA"
+
+
+class AzulJavaPackageType(StrEnum):
+ Jdk = "jdk"
+ Jre = "jre"
+
+
+class AzulReleaseType(StrEnum):
+ CPU = "CPU"
+ PSU = "PSU"
+ LU = "LU"
+
+
+class AzulOs(StrEnum):
+ Linux = "linux"
+ Macos = "macos"
+ Qnx = "qnx"
+ Windows = "windows"
+ Solaris = "solaris"
+
+
+class AzulLibCType(StrEnum):
+ Glibc = "glibc"
+ Uclibc = "uclibc"
+ Musl = "musl"
+
+
+class AzulCPUGen(StrEnum):
+ V5 = "v5"
+ V6kV6kz = "v6k_v6kz"
+ V6t2 = "v6t2"
+ V7 = "v7"
+ V8 = "v8"
+
+
+class AzulArch(StrEnum):
+ Arm = "arm"
+ X86 = "x86"
+ Mips = "mips"
+ Ppc = "ppc"
+ Sparcv9 = "sparcv9"
+ Sparc = "sparc"
+
+
+class AzulHwBitness(IntEnum):
+ X32 = 32
+ X64 = 64
+
+
+class AzulAbi(StrEnum):
+ HardFloat = "hard_float"
+ SoftFloat = "soft_float"
+ Spe = "spe"
+ Any = "any"
+
+
+class AzulArchiveType(StrEnum):
+ Deb = "deb"
+ Rpm = "rpm"
+ Dmg = "dmg"
+ Targz = "tar.gz"
+ Zip = "zip"
+ Cab = "cab"
+ Msi = "msi"
+
+
+class AzulReleaseStatus(StrEnum):
+ Eval = "eval"
+ Ea = "ea"
+ Ga = "ga"
+ Both = "both"
+
+
+class AzulSupportTerm(StrEnum):
+ Sts = "sts"
+ Mts = "mts"
+ Lts = "lts"
+
+
+class AzulCertifications(StrEnum):
+ Tck = "tck"
+ _Aqavit = "aqavit"
+ none = "none"
+
+
+class AzulSignatureType(StrEnum):
+ Openpgp = "openpgp"
+
+
+class AzulOsQueryParam(StrEnum):
+ Macos = "macos"
+ Windows = "windows"
+ Linux = "linux"
+ LinuxMusl = "linux-musl"
+ LinuxGlibc = "linux-glibc"
+ Qnx = "qnx"
+ Solaris = "solaris"
+
+
+class AzulArchQueryParam(StrEnum):
+ X86 = "x86"
+ X64 = "x64"
+ Amd64 = "amd64"
+ I686 = "i686"
+ Arm = "arm"
+ Aarch64 = "aarch64"
+ Aarch32 = "aarch32"
+ Aarch32sf = "aarch32sf"
+ Aarch32hf = "aarch32hf"
+ Ppc = "ppc"
+ Ppc64 = "ppc64"
+ Ppc64hf = "ppc64hf"
+ Ppc32 = "ppc32"
+ Ppc32spe = "ppc32spe"
+ Ppc32hf = "ppc32hf"
+ Sparc = "sparc"
+ Sparc32 = "sparc32"
+ Sparcv9 = "sparcv9"
+ Sparcv9_64 = "sparcv9-64"
+
+
+AZUL_API_BASE = "https://api.azul.com/metadata/v1"
+AZUL_API_PACKAGES = f"{AZUL_API_BASE}/zulu/packages/"
+AZUL_API_PACKAGE_DETAIL = f"{AZUL_API_BASE}/zulu/packages/{{package_uuid}}"
+
+
+class AzulApiPackagesQuery(APIQuery):
+ java_version: Optional[str] = None
+ os: Optional[AzulOsQueryParam] = None
+ arch: Optional[AzulArchQueryParam] = None
+ archive_type: Optional[AzulArchiveType] = None
+ java_package_type: Optional[AzulJavaPackageType] = None
+ javafx_bundled: Optional[bool] = None
+ crac_supported: Optional[bool] = None
+ support_term: Optional[AzulSupportTerm] = None
+ release_type: Optional[AzulReleaseType] = None
+ latest: Optional[bool] = None
+ distro_version: Optional[str] = None
+ java_package_features: list[str] = []
+ release_status: Optional[AzulReleaseStatus] = None
+ availability_types: list[AzulAvailabilityType] = []
+ certifications: list[AzulCertifications] = []
+ include_fields: list[str] = []
+ page: int = 0
+ page_size: int = 100
+
+
+def azulApiPackagesUrl(query: AzulApiPackagesQuery = AzulApiPackagesQuery()):
+ url = urlparse(AZUL_API_PACKAGES)
+ return urlunparse(url._replace(query=query.to_query()))
+
+
+def azulApiPackageDetailUrl(package_uuid: str):
+ return AZUL_API_PACKAGE_DETAIL.format(package_uuid=package_uuid)
+
+
+class ZuluSignatureDetail(MetaBase):
+ type: AzulSignatureType
+ url: str
+ details: dict[str, Any]
+ signature_index: int
+ signature: str
+
+
+class ZuluPackageDetail(MetaBase):
+ package_uuid: str
+ name: Optional[str]
+ md5_hash: Optional[str]
+ sha256_hash: Optional[str]
+ build_date: datetime
+ last_modified: datetime
+ download_url: str
+ product: AzulProduct
+ availability_type: AzulAvailabilityType
+ java_version: list[int]
+ openjdk_build_number: Optional[int]
+ java_package_type: AzulJavaPackageType
+ javafx_bundled: bool
+ release_type: AzulReleaseType
+ os: AzulOs
+ lib_c_type: Optional[AzulLibCType]
+ cpu_gen: Optional[list[AzulCPUGen]]
+ arch: AzulArch
+ hw_bitness: AzulHwBitness
+ abi: AzulAbi
+ archive_type: AzulArchiveType
+ release_status: AzulReleaseStatus
+ support_term: AzulSupportTerm
+ certifications: Optional[list[AzulCertifications]]
+ latest: Optional[bool]
+ size: int
+ distro_version: list[int]
+ signatures: list[ZuluSignatureDetail]
+
+
+class ZuluPackage(MetaBase):
+ package_uuid: str
+ name: Optional[str]
+ java_version: list[int]
+ openjdk_build_number: Optional[int]
+ latest: Optional[bool]
+ download_url: str
+ product: Optional[AzulProduct]
+ distro_version: list[int]
+ availability_type: Optional[AzulAvailabilityType]
+
+
+class ZuluPackageList(MetaBase):
+ __root__: list[ZuluPackage]
+
+ def __iter__(self) -> Generator[tuple[str, ZuluPackage], None, None]:
+ yield from ((str(i), val) for i, val in enumerate(self.__root__))
+
+ def __getitem__(self, item: int) -> ZuluPackage:
+ return self.__root__[item]
+
+ def append(self, pkg: ZuluPackage):
+ self.__root__.append(pkg)
+
+
+class ZuluPackagesDetail(MetaBase):
+ __root__: list[ZuluPackageDetail]
+
+ def __iter__(self) -> Generator[tuple[str, ZuluPackageDetail], None, None]:
+ yield from ((str(i), val) for i, val in enumerate(self.__root__))
+
+ def __getitem__(self, item: int) -> ZuluPackageDetail:
+ return self.__root__[item]
+
+ def append(self, pkg: ZuluPackageDetail):
+ self.__root__.append(pkg)
+
+
+MOJANG_OS_NAMES = ["mac-os", "linux", "windows"]
+
+MOJANG_OS_ARCHITECTURES = [
+ "x64" "x86",
+ "arm64",
+ "arm32",
+]
diff --git a/meta/model/mojang.py b/meta/model/mojang.py
index 221f8e074e..6fb71e7e73 100644
--- a/meta/model/mojang.py
+++ b/meta/model/mojang.py
@@ -1,5 +1,6 @@
from datetime import datetime
from typing import Optional, List, Dict, Any, Iterator
+from .enum import StrEnum
from pydantic import validator, Field
@@ -17,6 +18,9 @@ from . import (
SUPPORTED_LAUNCHER_VERSION = 21
SUPPORTED_COMPLIANCE_LEVEL = 1
DEFAULT_JAVA_MAJOR = 8 # By default, we should recommend Java 8 if we don't know better
+DEFAULT_JAVA_NAME = (
+ "jre-legacy" # By default, we should recommend Java 8 if we don't know better
+)
COMPATIBLE_JAVA_MAPPINGS = {16: [17]}
SUPPORTED_FEATURES = ["is_quick_play_multiplayer"]
@@ -193,11 +197,74 @@ class MojangLogging(MetaBase):
type: str
+class MojangJavaComponent(StrEnum):
+ JreLegacy = "jre-legacy"
+ Alpha = "java-runtime-alpha"
+ Beta = "java-runtime-beta"
+ Gamma = "java-runtime-gamma"
+ GammaSnapshot = "java-runtime-gamma-snapshot"
+ Exe = "minecraft-java-exe"
+ Delta = "java-runtime-delta"
+
+
class JavaVersion(MetaBase):
- component: str = "jre-legacy"
+ component: MojangJavaComponent = MojangJavaComponent.JreLegacy
major_version: int = Field(8, alias="majorVersion")
+class MojangJavaIndexAvailability(MetaBase):
+ group: int
+ progress: int
+
+
+class MojangJavaIndexManifest(MetaBase):
+ sha1: str
+ size: int
+ url: str
+
+
+class MojangJavaIndexVersion(MetaBase):
+ name: str
+ released: datetime
+
+
+class MojangJavaRuntime(MetaBase):
+ availability: MojangJavaIndexAvailability
+ manifest: MojangJavaIndexManifest
+ version: MojangJavaIndexVersion
+
+
+class MojangJavaIndexEntry(MetaBase):
+ __root__: dict[MojangJavaComponent, list[MojangJavaRuntime]]
+
+ def __iter__(self) -> Iterator[MojangJavaComponent]:
+ return iter(self.__root__)
+
+ def __getitem__(self, item) -> list[MojangJavaRuntime]:
+ return self.__root__[item]
+
+
+class MojangJavaOsName(StrEnum):
+ Gamecore = "gamecore"
+ Linux = "linux"
+ Linuxi386 = "linux-i386"
+ MacOs = "mac-os"
+ MacOSArm64 = "mac-os-arm64"
+ WindowsArm64 = "windows-arm64"
+ WindowsX64 = "windows-x64"
+ WindowsX86 = "windows-x86"
+
+
+class JavaIndex(MetaBase):
+ __root__: dict[MojangJavaOsName, MojangJavaIndexEntry]
+
+ def __iter__(self) -> Iterator[MojangJavaOsName]:
+ return iter(self.__root__)
+
+ def __getitem__(self, item) -> MojangJavaIndexEntry:
+ return self.__root__[item]
+
+
class MojangVersion(MetaBase):
@validator("minimum_launcher_version")
def validate_minimum_launcher_version(cls, v):
@@ -256,10 +323,12 @@ class MojangVersion(MetaBase):
raise Exception(f"Unsupported compliance level {self.compliance_level}")
major = DEFAULT_JAVA_MAJOR
+ javaName = DEFAULT_JAVA_NAME
if (
self.javaVersion is not None
): # some versions don't have this. TODO: maybe maintain manual overrides
major = self.javaVersion.major_version
+ javaName = self.javaVersion.component
compatible_java_majors = [major]
if (
@@ -281,6 +350,7 @@ class MojangVersion(MetaBase):
release_time=self.release_time,
type=new_type,
compatible_java_majors=compatible_java_majors,
+ compatible_java_name=javaName,
additional_traits=addn_traits,
main_jar=main_jar,
)
diff --git a/meta/run/generate_java.py b/meta/run/generate_java.py
new file mode 100644
index 0000000000..fd32308217
--- /dev/null
+++ b/meta/run/generate_java.py
@@ -0,0 +1,481 @@
+import copy
+import datetime
+import os
+from typing import Optional
+from functools import reduce
+
+from meta.common import ensure_component_dir, launcher_path, upstream_path
+
+from meta.common.java import (
+ JAVA_MINECRAFT_COMPONENT,
+ JAVA_ADOPTIUM_COMPONENT,
+ JAVA_AZUL_COMPONENT,
+ ADOPTIUM_DIR,
+ ADOPTIUM_VERSIONS_DIR,
+ AZUL_DIR,
+ AZUL_VERSIONS_DIR,
+)
+from meta.model import MetaPackage
+from meta.model.java import (
+ JavaRuntimeOS,
+ JavaRuntimeVersion,
+ JavaRuntimeMeta,
+ JavaVersionMeta,
+ JavaPackageType,
+ JavaChecksumMeta,
+ JavaChecksumType,
+ JavaRuntimeDownloadType,
+ AdoptiumAvailableReleases,
+ AdoptiumReleases,
+ AdoptiumRelease,
+ AdoptiumImageType,
+ AdoptiumBinary,
+ ZuluPackageList,
+ ZuluPackageDetail,
+ AzulJavaPackageType,
+ AzulArch,
+)
+
+from meta.common.mojang import (
+ JAVA_MANIFEST_FILE,
+)
+
+from meta.model.mojang import (
+ JavaIndex,
+ MojangJavaComponent,
+ MojangJavaOsName,
+ MojangJavaRuntime,
+)
+
+LAUNCHER_DIR = launcher_path()
+UPSTREAM_DIR = upstream_path()
+
+
+MOJANG_OS_ARCHITECTURES = [
+ "x64",
+ "x86",
+ "arm64",
+ "arm32",
+]
+
+MOJANG_OS_ARCHITECTURE_TRANSLATIONS = {
+ 64: "x64",
+ 32: "x86",
+ "x32": "x86",
+ "i386": "x86",
+ "aarch64": "arm64",
+ "x86_64": "x64",
+ "arm": "arm32",
+}
+
+
+def translate_arch(arch: str | int):
+ if isinstance(arch, str):
+ arch = arch.lower()
+ if arch in MOJANG_OS_ARCHITECTURES:
+ return arch
+ elif arch in MOJANG_OS_ARCHITECTURE_TRANSLATIONS:
+ return MOJANG_OS_ARCHITECTURE_TRANSLATIONS[arch]
+ else:
+ return None
+
+
+MOJANG_OS_NAMES = [
+ "mac-os",
+ "linux",
+ "windows",
+]
+
+MOJANG_OS_TRANSLATIONS = {
+ "osx": "mac-os",
+ "mac": "mac-os",
+ "macos": "mac-os",
+}
+
+
+def translate_os(os: str):
+ os = os.lower()
+ if os in MOJANG_OS_NAMES:
+ return os
+ elif os in MOJANG_OS_TRANSLATIONS:
+ return MOJANG_OS_TRANSLATIONS[os]
+ else:
+ return None
+
+
+def mojang_os_to_java_os(mojang_os: MojangJavaOsName) -> JavaRuntimeOS:
+ match mojang_os:
+ case MojangJavaOsName.Linux:
+ return JavaRuntimeOS.LinuxX64
+ case MojangJavaOsName.Linuxi386:
+ return JavaRuntimeOS.LinuxX86
+ case MojangJavaOsName.MacOs:
+ return JavaRuntimeOS.MacOsX64
+ case MojangJavaOsName.MacOSArm64:
+ return JavaRuntimeOS.MacOsArm64
+ case MojangJavaOsName.WindowsArm64:
+ return JavaRuntimeOS.WindowsArm64
+ case MojangJavaOsName.WindowsX64:
+ return JavaRuntimeOS.WindowsX64
+ case MojangJavaOsName.WindowsX86:
+ return JavaRuntimeOS.WindowsX86
+ case _:
+ return JavaRuntimeOS.Unknown
+
+
+def mojang_component_to_major(mojang_component: MojangJavaComponent) -> int:
+ match mojang_component:
+ case MojangJavaComponent.JreLegacy:
+ return 8
+ case MojangJavaComponent.Alpha:
+ return 17
+ case MojangJavaComponent.Beta:
+ return 17
+ case MojangJavaComponent.Gamma:
+ return 17
+ case MojangJavaComponent.GammaSnapshot:
+ return 17
+ case MojangJavaComponent.Exe:
+ return 0
+ case MojangJavaComponent.Delta:
+ return 21
+ case _:
+ return 0
+
+
+def mojang_runtime_to_java_runtime(
+ mojang_runtime: MojangJavaRuntime,
+ mojang_component: MojangJavaComponent,
+ runtime_os: JavaRuntimeOS,
+) -> JavaRuntimeMeta:
+ major, _, security = mojang_runtime.version.name.partition("u")
+ if major and security:
+ version_parts = [int(major), 0, int(security)]
+ else:
+ version_parts = [int(part) for part in mojang_runtime.version.name.split(".")]
+
+ while len(version_parts) < 3:
+ version_parts.append(0)
+
+ build = None
+ if len(version_parts) >= 4:
+ build = version_parts[3]
+
+ version = JavaVersionMeta(
+ major=version_parts[0],
+ minor=version_parts[1],
+ security=version_parts[2],
+ build=build,
+ name=mojang_runtime.version.name,
+ )
+ return JavaRuntimeMeta(
+ name=mojang_component,
+ vendor="mojang",
+ url=mojang_runtime.manifest.url,
+ releaseTime=mojang_runtime.version.released,
+ checksum=JavaChecksumMeta(
+ type=JavaChecksumType.Sha1, hash=mojang_runtime.manifest.sha1
+ ),
+ downloadType=JavaRuntimeDownloadType.Manifest,
+ packageType=JavaPackageType.Jre,
+ version=version,
+ runtime_os=runtime_os,
+ )
+
+
+def adoptium_release_binary_to_java_runtime(
+ rls: AdoptiumRelease,
+ binary: AdoptiumBinary,
+ runtime_os: JavaRuntimeOS,
+) -> JavaRuntimeMeta:
+ assert binary.package is not None
+
+ checksum = None
+ if binary.package.checksum is not None:
+ checksum = JavaChecksumMeta(
+ type=JavaChecksumType.Sha256, hash=binary.package.checksum
+ )
+
+ pkg_type = JavaPackageType(str(binary.image_type))
+
+ version = JavaVersionMeta(
+ major=rls.version_data.major if rls.version_data.major is not None else 0,
+ minor=rls.version_data.minor if rls.version_data.minor is not None else 0,
+ security=(
+ rls.version_data.security if rls.version_data.security is not None else 0
+ ),
+ build=rls.version_data.build,
+ )
+ rls_name = f"{rls.vendor}_temurin_{binary.image_type}{version}"
+ return JavaRuntimeMeta(
+ name=rls_name,
+ vendor=rls.vendor,
+ url=binary.package.link,
+ releaseTime=rls.timestamp,
+ checksum=checksum,
+ downloadType=JavaRuntimeDownloadType.Archive,
+ packageType=pkg_type,
+ version=version,
+ runtime_os=runtime_os,
+ )
+
+
+def azul_package_to_java_runtime(
+ pkg: ZuluPackageDetail, runtime_os: JavaRuntimeOS
+) -> JavaRuntimeMeta:
+ version_parts = copy.copy(pkg.java_version)
+
+ build = None
+ while len(version_parts) < 3:
+ version_parts.append(0)
+
+ if len(version_parts) >= 4:
+ build = version_parts[3]
+
+ version = JavaVersionMeta(
+ major=version_parts[0],
+ minor=version_parts[1],
+ security=version_parts[2],
+ build=build,
+ )
+
+ pkg_type = JavaPackageType(str(pkg.java_package_type))
+
+ rls_name = f"azul_{pkg.product}_{pkg.java_package_type}{version}"
+
+ checksum = None
+ if pkg.sha256_hash is not None:
+ checksum = JavaChecksumMeta(type=JavaChecksumType.Sha256, hash=pkg.sha256_hash)
+
+ return JavaRuntimeMeta(
+ name=rls_name,
+ vendor="azul",
+ url=pkg.download_url,
+ releaseTime=pkg.build_date,
+ checksum=checksum,
+ downloadType=JavaRuntimeDownloadType.Archive,
+ packageType=pkg_type,
+ version=version,
+ runtime_os=runtime_os,
+ )
+
+
+def writeJavas(javas: dict[int, list[JavaRuntimeMeta]], uid: str):
+ def oldest_timestamp(a: datetime.datetime | None, b: datetime.datetime):
+ if a is None or a > b:
+ return b
+ return a
+
+ ensure_component_dir(uid)
+
+ # small hack to sort the versions after major
+ javas = dict(sorted(javas.items(), key=lambda item: item[0]))
+ timestamps: dict[int, datetime.datetime | None] = {}
+ prevDate: datetime.datetime | None = None
+ for major, runtimes in javas.items():
+ releaseTime = reduce(
+ oldest_timestamp,
+ (runtime.release_time for runtime in runtimes),
+ None,
+ )
+ if prevDate is not None and releaseTime < prevDate:
+ releaseTime = prevDate + datetime.timedelta(seconds=1)
+ prevDate = releaseTime
+ timestamps[major] = releaseTime
+
+ for major, runtimes in javas.items():
+ version_file = os.path.join(LAUNCHER_DIR, uid, f"java{major}.json")
+ java_version = JavaRuntimeVersion(
+ name=f"Java {major}",
+ uid=uid,
+ version=f"java{major}",
+ releaseTime=timestamps.get(major),
+ runtimes=runtimes,
+ )
+ java_version.write(version_file)
+
+ package = MetaPackage(uid=uid, name="Java Runtimes", recommended=[])
+ package.write(os.path.join(LAUNCHER_DIR, uid, "package.json"))
+
+
+def main():
+ javas: dict[int, list[JavaRuntimeMeta]] = {}
+ extra_mojang_javas: dict[int, list[JavaRuntimeMeta]] = {}
+
+ def add_java_runtime(runtime: JavaRuntimeMeta, major: int):
+ if major not in javas:
+ javas[major] = list[JavaRuntimeMeta]()
+ print(f"Regestering runtime: {runtime.name} for Java {major}")
+ javas[major].append(runtime)
+
+ # only add specific versions to the list
+ if (
+ (
+ runtime.runtime_os
+ in [JavaRuntimeOS.MacOsArm64, JavaRuntimeOS.WindowsArm64]
+ and major == 8
+ )
+ or (
+ runtime.runtime_os
+ in [
+ JavaRuntimeOS.WindowsArm32,
+ JavaRuntimeOS.LinuxArm32,
+ JavaRuntimeOS.LinuxArm64,
+ ]
+ and major in [8, 17, 21]
+ )
+ or (runtime.runtime_os == JavaRuntimeOS.LinuxX86 and major in [17, 21])
+ ):
+ if major not in extra_mojang_javas:
+ extra_mojang_javas[major] = list[JavaRuntimeMeta]()
+ extra_mojang_javas[major].append(runtime)
+
+ print("Processing Adoptium Releases")
+ adoptium_path = os.path.join(UPSTREAM_DIR, ADOPTIUM_DIR, "available_releases.json")
+ if os.path.exists(adoptium_path):
+ adoptium_available_releases = AdoptiumAvailableReleases.parse_file(
+ adoptium_path
+ )
+ for major in adoptium_available_releases.available_releases:
+ adoptium_releases = AdoptiumReleases.parse_file(
+ os.path.join(UPSTREAM_DIR, ADOPTIUM_VERSIONS_DIR, f"java{major}.json")
+ )
+ for _, rls in adoptium_releases:
+ for binary in rls.binaries:
+ if (
+ binary.package is None
+ or binary.image_type is not AdoptiumImageType.Jre
+ ):
+ continue
+ binary_arch = translate_arch(str(binary.architecture))
+ binary_os = translate_os(str(binary.os))
+ if binary_arch is None or binary_os is None:
+ print(f"Ignoring release for {binary.os} {binary.architecture}")
+ continue
+
+ java_os = JavaRuntimeOS(f"{binary_os}-{binary_arch}")
+ runtime = adoptium_release_binary_to_java_runtime(
+ rls, binary, java_os
+ )
+ add_java_runtime(runtime, major)
+
+ writeJavas(javas=javas, uid=JAVA_ADOPTIUM_COMPONENT)
+ javas = {}
+ print("Processing Azul Packages")
+ azul_path = os.path.join(UPSTREAM_DIR, AZUL_DIR, "packages.json")
+ if os.path.exists(azul_path):
+ azul_packages = ZuluPackageList.parse_file(azul_path)
+ for _, pkg in azul_packages:
+ pkg_detail = ZuluPackageDetail.parse_file(
+ os.path.join(
+ UPSTREAM_DIR, AZUL_VERSIONS_DIR, f"{pkg.package_uuid}.json"
+ )
+ )
+ major = pkg_detail.java_version[0]
+ if major < 8 or pkg_detail.java_package_type is not AzulJavaPackageType.Jre:
+ continue # we will never need java versions less than 8
+
+ pkg_os = translate_os(str(pkg_detail.os))
+ if pkg_detail.arch == AzulArch.Arm:
+ pkg_arch = translate_arch(f"{pkg_detail.arch}{pkg_detail.hw_bitness}")
+ elif pkg_detail.arch == AzulArch.X86:
+ pkg_arch = translate_arch(int(pkg_detail.hw_bitness))
+ else:
+ pkg_arch = None
+ if pkg_arch is None or pkg_os is None:
+ print(
+ f"Ignoring release for {pkg_detail.os} {pkg_detail.arch}_{pkg_detail.hw_bitness}"
+ )
+ continue
+
+ java_os = JavaRuntimeOS(f"{pkg_os}-{pkg_arch}")
+ runtime = azul_package_to_java_runtime(pkg_detail, java_os)
+ add_java_runtime(runtime, major)
+ writeJavas(javas=javas, uid=JAVA_AZUL_COMPONENT)
+ javas = {}
+
+ # constructs the missing mojang javas based on adoptium or azul
+ def get_mojang_extra_java(
+ mojang_component: MojangJavaComponent, java_os: JavaRuntimeOS
+ ) -> JavaRuntimeMeta | None:
+ java_major = mojang_component_to_major(mojang_component)
+ if not java_major in extra_mojang_javas:
+ return None
+ posible_javas = list(
+ filter(lambda x: x.runtime_os == java_os, extra_mojang_javas[java_major])
+ )
+ if len(posible_javas) == 0:
+ return None
+ prefered_vendor = list(filter(lambda x: x.vendor != "azul", posible_javas))
+ if len(prefered_vendor) == 0:
+ prefered_vendor = posible_javas
+ prefered_vendor.sort(key=lambda x: x.version, reverse=True)
+ runtime = prefered_vendor[0]
+ runtime.name = mojang_component
+ return runtime
+
+ print("Processing Mojang Javas")
+ mojang_java_manifest = JavaIndex.parse_file(
+ os.path.join(UPSTREAM_DIR, JAVA_MANIFEST_FILE)
+ )
+ for mojang_os_name in mojang_java_manifest:
+ if mojang_os_name == MojangJavaOsName.Gamecore:
+ continue # empty
+ java_os = mojang_os_to_java_os(mojang_os_name)
+ for comp in mojang_java_manifest[mojang_os_name]:
+ if comp == MojangJavaComponent.Exe:
+ continue # doesn't appear to be used and not marked with a full verison so I don't trust it
+ mojang_runtimes = mojang_java_manifest[mojang_os_name][comp]
+ if len(mojang_runtimes) == 0:
+ if mojang_os_name in [
+ MojangJavaOsName.WindowsArm64,
+ MojangJavaOsName.MacOSArm64,
+ ]:
+ if comp in [MojangJavaComponent.Alpha, MojangJavaComponent.Beta]:
+ mojang_runtimes = mojang_java_manifest[mojang_os_name][
+ MojangJavaComponent.Gamma
+ ]
+ elif (
+ comp == MojangJavaComponent.JreLegacy
+ ): # arm version of win and mac is missing the legacy java
+ runtime = get_mojang_extra_java(comp, java_os)
+ if runtime != None:
+ add_java_runtime(runtime, mojang_component_to_major(comp))
+ if (
+ mojang_os_name == MojangJavaOsName.Linuxi386
+ and comp != MojangJavaComponent.JreLegacy
+ ): # the linux x86 is missing all but legacy
+ runtime = get_mojang_extra_java(comp, java_os)
+ if runtime != None:
+ add_java_runtime(runtime, mojang_component_to_major(comp))
+ for mojang_runtime in mojang_runtimes:
+ if comp == MojangJavaComponent.JreLegacy:
+ major = 8
+ else:
+ major = int(mojang_runtime.version.name.partition(".")[0])
+ runtime = mojang_runtime_to_java_runtime(mojang_runtime, comp, java_os)
+ add_java_runtime(runtime, major)
+ # mojang doesn't provide any versions for the following systems so borrow info from adoptium/azul
+ for java_os in [
+ JavaRuntimeOS.WindowsArm32,
+ JavaRuntimeOS.LinuxArm32,
+ JavaRuntimeOS.LinuxArm64,
+ ]:
+ for comp in [
+ MojangJavaComponent.JreLegacy,
+ MojangJavaComponent.Alpha,
+ MojangJavaComponent.Beta,
+ MojangJavaComponent.Gamma,
+ MojangJavaComponent.GammaSnapshot,
+ MojangJavaComponent.Delta,
+ ]:
+ runtime = get_mojang_extra_java(comp, java_os)
+ if runtime != None:
+ add_java_runtime(runtime, mojang_component_to_major(comp))
+
+ writeJavas(javas=javas, uid=JAVA_MINECRAFT_COMPONENT)
+ javas = {}
+
+
+if __name__ == "__main__":
+ main()
diff --git a/meta/run/update_java.py b/meta/run/update_java.py
new file mode 100644
index 0000000000..326fb5f924
--- /dev/null
+++ b/meta/run/update_java.py
@@ -0,0 +1,158 @@
+import os
+
+from meta.common import upstream_path, ensure_upstream_dir, default_session
+from meta.common.java import (
+ BASE_DIR,
+ ADOPTIUM_DIR,
+ AZUL_DIR,
+ ADOPTIUM_VERSIONS_DIR,
+ AZUL_VERSIONS_DIR,
+)
+from meta.model.java import (
+ ADOPTIUM_API_AVAILABLE_RELEASES,
+ adoptiumAPIFeatureReleasesUrl,
+ AdoptiumImageType,
+ AdoptiumAPIFeatureReleasesQuery,
+ AdoptiumAvailableReleases,
+ AdoptiumRelease,
+ AdoptiumReleases,
+ azulApiPackagesUrl,
+ AzulApiPackagesQuery,
+ ZuluPackage,
+ ZuluPackageList,
+ AzulArchiveType,
+ AzulReleaseStatus,
+ AzulAvailabilityType,
+ AzulJavaPackageType,
+ azulApiPackageDetailUrl,
+ ZuluPackageDetail,
+ ZuluPackagesDetail,
+)
+
+UPSTREAM_DIR = upstream_path()
+
+ensure_upstream_dir(BASE_DIR)
+ensure_upstream_dir(ADOPTIUM_DIR)
+ensure_upstream_dir(AZUL_DIR)
+ensure_upstream_dir(ADOPTIUM_VERSIONS_DIR)
+ensure_upstream_dir(AZUL_VERSIONS_DIR)
+
+
+sess = default_session()
+
+
+def main():
+ print("Getting Adoptium Release Manifests ")
+ r = sess.get(ADOPTIUM_API_AVAILABLE_RELEASES)
+ r.raise_for_status()
+
+ available = AdoptiumAvailableReleases(**r.json())
+
+ available_releases_file = os.path.join(
+ UPSTREAM_DIR, ADOPTIUM_DIR, "available_releases.json"
+ )
+ available.write(available_releases_file)
+
+ for feature in available.available_releases:
+ print("Getting Manifests for Adoptium feature release:", feature)
+
+ page_size = 10
+
+ releases_for_feature: list[AdoptiumRelease] = []
+ page = 0
+ while True:
+ query = AdoptiumAPIFeatureReleasesQuery(
+ image_type=AdoptiumImageType.Jre, page_size=page_size, page=page
+ )
+ api_call = adoptiumAPIFeatureReleasesUrl(feature, query=query)
+ print("Fetching JRE Page:", page, api_call)
+ r_rls = sess.get(api_call)
+ if r_rls.status_code == 404:
+ break
+ else:
+ r_rls.raise_for_status()
+
+ releases = list(AdoptiumRelease(**rls) for rls in r_rls.json())
+ releases_for_feature.extend(releases)
+
+ if len(r_rls.json()) < page_size:
+ break
+ page += 1
+
+ print("Total Adoptium releases for feature:", len(releases_for_feature))
+ releases = AdoptiumReleases(__root__=releases_for_feature)
+ feature_file = os.path.join(
+ UPSTREAM_DIR, ADOPTIUM_VERSIONS_DIR, f"java{feature}.json"
+ )
+ releases.write(feature_file)
+
+ print("Getting Azul Release Manifests")
+ zulu_packages: list[ZuluPackage] = []
+ page = 1
+ page_size = 100
+ while True:
+
+ query = AzulApiPackagesQuery(
+ archive_type=AzulArchiveType.Zip,
+ release_status=AzulReleaseStatus.Ga,
+ availability_types=[AzulAvailabilityType.CA],
+ java_package_type=AzulJavaPackageType.Jre,
+ javafx_bundled=False,
+ latest=True,
+ page=page,
+ page_size=page_size,
+ )
+ api_call = azulApiPackagesUrl(query=query)
+
+ print("Processing Page:", page, api_call)
+
+ r = sess.get(api_call)
+ if r.status_code == 404:
+ break
+ else:
+ r.raise_for_status()
+
+ packages = list(ZuluPackage(**pkg) for pkg in r.json())
+ zulu_packages.extend(packages)
+ if len(packages) < page_size:
+ break
+ page += 1
+
+ print("Total Azul Packages:", len(zulu_packages))
+ packages = ZuluPackageList(__root__=zulu_packages)
+ azul_manifest_file = os.path.join(UPSTREAM_DIR, AZUL_DIR, "packages.json")
+ packages.write(azul_manifest_file)
+
+ azul_major_versions: dict[int, ZuluPackagesDetail] = {}
+
+ for _, pkg in packages:
+
+ major_version = pkg.java_version[0]
+ if major_version not in azul_major_versions:
+ azul_major_versions[major_version] = ZuluPackagesDetail(__root__=[])
+
+ pkg_file = os.path.join(
+ UPSTREAM_DIR, AZUL_VERSIONS_DIR, f"{pkg.package_uuid}.json"
+ )
+ if os.path.exists(pkg_file) and os.path.isfile(pkg_file):
+ pkg_detail = ZuluPackageDetail.parse_file(pkg_file)
+ azul_major_versions[major_version].append(pkg_detail)
+ else:
+
+ api_call = azulApiPackageDetailUrl(pkg.package_uuid)
+ print("Fetching Azul package manifest:", pkg.package_uuid)
+ r_pkg = sess.get(api_call)
+ r_pkg.raise_for_status()
+
+ pkg_detail = ZuluPackageDetail(**r_pkg.json())
+ pkg_detail.write(pkg_file)
+ azul_major_versions[major_version].append(pkg_detail)
+
+ for major in azul_major_versions:
+ major_file = os.path.join(UPSTREAM_DIR, AZUL_VERSIONS_DIR, f"java{major}.json")
+ azul_major_versions[major].write(major_file)
+
+
+if __name__ == "__main__":
+ main()
+#
diff --git a/meta/run/update_mojang.py b/meta/run/update_mojang.py
index defc371c1c..ddadc16e89 100755
--- a/meta/run/update_mojang.py
+++ b/meta/run/update_mojang.py
@@ -12,6 +12,7 @@ from meta.common.mojang import (
ASSETS_DIR,
STATIC_EXPERIMENTS_FILE,
STATIC_OLD_SNAPSHOTS_FILE,
+ JAVA_MANIFEST_FILE,
)
from meta.model.mojang import (
MojangIndexWrap,
@@ -20,6 +21,7 @@ from meta.model.mojang import (
ExperimentIndexWrap,
OldSnapshotIndexWrap,
OldSnapshotIndex,
+ JavaIndex,
)
UPSTREAM_DIR = upstream_path()
@@ -81,6 +83,20 @@ def fetch_version(path, url):
return version_json
+MOJANG_JAVA_URL = "https://piston-meta.mojang.com/v1/products/java-runtime/2ec0cc96c44e5a76b9c8b7c39df7210883d12871/all.json"
+
+
+def update_javas():
+ r = sess.get(MOJANG_JAVA_URL)
+ r.raise_for_status()
+
+ remote_javas = JavaIndex(__root__=r.json())
+
+ java_manifest_path = os.path.join(UPSTREAM_DIR, JAVA_MANIFEST_FILE)
+
+ remote_javas.write(java_manifest_path)
+
+
def fetch_version_concurrent(remote_versions, x):
version = remote_versions.versions[x]
print(
@@ -165,6 +181,9 @@ def main():
remote_versions.index.write(version_manifest_path)
+ print("Getting Mojang Java runtime manfest")
+ update_javas()
+
if __name__ == "__main__":
main()