64 lines
2.3 KiB
Python
64 lines
2.3 KiB
Python
"""Optional Java runtime detection.
|
|
|
|
``opendataloader-pdf`` (structured PDF→JSON extraction, see chat_agent.py) is a
|
|
Python wrapper around a JAVA CLI tool — the first Java dependency anywhere in
|
|
this app. Same optional-native-binary shape as doc_extract.py::find_soffice:
|
|
env override → PATH → common install directories → ``None`` if not found.
|
|
Callers must degrade gracefully — a missing JVM just means that one capability
|
|
isn't available on this machine, not an error.
|
|
"""
|
|
from __future__ import annotations
|
|
|
|
import os
|
|
import re
|
|
import shutil
|
|
from pathlib import Path
|
|
|
|
_EXE = "java.exe" if os.name == "nt" else "java"
|
|
|
|
# Common JDK/JRE install roots, newest-version subfolder picked first.
|
|
_COMMON_ROOTS = (
|
|
r"C:\Program Files\Java",
|
|
r"C:\Program Files\Eclipse Adoptium",
|
|
r"C:\Program Files (x86)\Java",
|
|
"/Library/Java/JavaVirtualMachines",
|
|
"/usr/lib/jvm",
|
|
)
|
|
|
|
|
|
def _version_key(path: Path) -> tuple:
|
|
"""Natural-sort key so "jdk-17..." ranks above "jdk-8..." — a plain string
|
|
sort ranks '8' > '1' and would pick the OLDER JDK when major-version digit
|
|
counts differ (e.g. Eclipse Adoptium installs several majors side by side
|
|
under one root)."""
|
|
return tuple(int(n) for n in re.findall(r"\d+", path.name))
|
|
|
|
|
|
def find_java() -> str | None:
|
|
"""Locate a Java launcher (``JAVA_HOME`` → PATH → common install dirs)."""
|
|
env = os.environ.get("JAVA_HOME")
|
|
if env:
|
|
candidate = Path(env) / "bin" / _EXE
|
|
if candidate.exists():
|
|
return str(candidate)
|
|
found = shutil.which("java")
|
|
if found:
|
|
return found
|
|
for base in _COMMON_ROOTS:
|
|
base_path = Path(base)
|
|
if not base_path.is_dir():
|
|
continue
|
|
try:
|
|
subdirs = sorted(base_path.iterdir(), key=_version_key, reverse=True)
|
|
except OSError:
|
|
continue # unreadable dir (permissions/AV) — not fatal, just try the next root
|
|
for sub in subdirs:
|
|
candidate = sub / "bin" / _EXE
|
|
if candidate.exists():
|
|
return str(candidate)
|
|
# macOS JDK bundles nest an extra Contents/Home.
|
|
mac_candidate = sub / "Contents" / "Home" / "bin" / _EXE
|
|
if mac_candidate.exists():
|
|
return str(mac_candidate)
|
|
return None
|